1  /*
2   * Copyright (c) 2022-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/components_ng/base/frame_node.h"
17  
18  #include <cstdint>
19  
20  #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
21  #include "core/common/layout_inspector.h"
22  #include "interfaces/inner_api/ui_session/ui_session_manager.h"
23  #include "frameworks/core/components_ng/pattern/web/web_pattern.h"
24  #endif
25  #include "base/geometry/ng/rect_t.h"
26  #include "core/pipeline/base/element_register.h"
27  #include "base/geometry/dimension.h"
28  #include "base/geometry/ng/offset_t.h"
29  #include "base/geometry/ng/point_t.h"
30  #include "base/log/ace_performance_monitor.h"
31  #include "base/log/ace_trace.h"
32  #include "base/log/dump_log.h"
33  #include "base/log/log_wrapper.h"
34  #include "base/memory/ace_type.h"
35  #include "base/memory/referenced.h"
36  #include "base/thread/cancelable_callback.h"
37  #include "base/thread/task_executor.h"
38  #include "base/utils/system_properties.h"
39  #include "base/utils/time_util.h"
40  #include "base/utils/utils.h"
41  #include "core/common/ace_application_info.h"
42  #include "core/common/container.h"
43  #include "core/common/recorder/event_recorder.h"
44  #include "core/common/recorder/node_data_cache.h"
45  #include "core/common/stylus/stylus_detector_mgr.h"
46  #include "core/components/common/layout/constants.h"
47  #include "core/components/common/layout/grid_system_manager.h"
48  #include "core/components_ng/base/extension_handler.h"
49  #include "core/components_ng/base/frame_scene_status.h"
50  #include "core/components_ng/base/inspector.h"
51  #include "core/components_ng/base/inspector_filter.h"
52  #include "core/components_ng/base/ui_node.h"
53  #include "core/components_ng/event/drag_event.h"
54  #include "core/components_ng/event/gesture_event_hub.h"
55  #include "core/components_ng/event/target_component.h"
56  #include "core/components_ng/gestures/recognizers/multi_fingers_recognizer.h"
57  #include "core/components_ng/layout/layout_algorithm.h"
58  #include "core/components_ng/layout/layout_wrapper.h"
59  #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
60  #include "core/components_ng/pattern/pattern.h"
61  #include "core/components_ng/pattern/stage/page_pattern.h"
62  #include "core/components_ng/property/measure_property.h"
63  #include "core/components_ng/property/measure_utils.h"
64  #include "core/components_ng/property/property.h"
65  #include "core/components_ng/render/paint_wrapper.h"
66  #include "core/components_ng/syntax/lazy_for_each_node.h"
67  #include "core/components_ng/syntax/repeat_virtual_scroll_node.h"
68  #include "core/components_v2/inspector/inspector_constants.h"
69  #include "core/event/touch_event.h"
70  #include "core/gestures/gesture_info.h"
71  #include "core/pipeline_ng/pipeline_context.h"
72  #include "core/pipeline_ng/ui_task_scheduler.h"
73  
74  namespace {
75  constexpr double VISIBLE_RATIO_MIN = 0.0;
76  constexpr double VISIBLE_RATIO_MAX = 1.0;
77  constexpr int32_t SUBSTR_LENGTH = 3;
78  const char DIMENSION_UNIT_VP[] = "vp";
79  constexpr int32_t SIZE_CHANGE_DUMP_SIZE = 5;
80  constexpr double MIN_WIDTH = 5.0;
81  constexpr double MIN_HEIGHT = 5.0;
82  constexpr double MIN_OPACITY = 0.1;
83  constexpr uint64_t MATRIX_CACHE_TIME_THRESHOLD = 15000000000;
84  /* suggestOpIncByte_s status mask, to indicate different aspects of node status
85   * related with suggestion OPINC improvements.
86   * for internal use; subject to change.
87   */
88  // suggest opinc marked.
89  constexpr uint8_t SUGGEST_OPINC_MARKED_MASK = 1;
90  // Whether the node can be suggest opinc marked.
91  constexpr uint8_t CAN_SUGGEST_OPINC_MASK = 1 << 1;
92  // The node already activated for suggest opinc.
93  constexpr uint8_t SUGGEST_OPINC_ACTIVATED_ONCE = 1 << 2;
94  // The node already checked for suggest opinc.
95  constexpr uint8_t SUGGEST_OPINC_CHCKED_ONCE = 1 << 3;
96  // The node has checked through for lazy new nodes.
97  constexpr uint8_t SUGGEST_OPINC_CHECKED_THROUGH = 1 << 4;
98  // Node has rendergroup marked.
99  constexpr uint8_t APP_RENDER_GROUP_MARKED_MASK = 1 << 7;
100  // OPINC must more then 2 leaf;
101  constexpr int32_t THRESH_CHILD_NO = 2;
102  // OPINC max ratio for scroll scope(height);
103  constexpr float HIGHT_RATIO_LIMIT = 0.8;
104  // Min area for OPINC
105  constexpr int32_t MIN_OPINC_AREA = 10000;
106  constexpr char UPDATE_FLAG_KEY[] = "updateFlag";
107  constexpr int32_t DEFAULT_PRECISION = 2;
108  } // namespace
109  namespace OHOS::Ace::NG {
110  
111  const std::set<std::string> FrameNode::layoutTags_ = { "Flex", "Stack", "Row", "Column", "WindowScene", "root",
112      "__Common__", "Swiper", "Grid", "GridItem", "page", "stage", "FormComponent", "Tabs", "TabContent" };
113  
114  class FrameNode::FrameProxy final : public RecursiveLock {
115  public:
116      struct FrameChildNode {
117          RefPtr<UINode> node;
118          uint32_t startIndex = 0;
119          uint32_t count = 0;
120      };
121  
Lock()122      void Lock() override
123      {
124          ++inUse_;
125      }
126  
Unlock()127      void Unlock() override
128      {
129          --inUse_;
130          if (!inUse_ && delayReset_) {
131              auto it = &hostNode_->frameProxy_;
132              while ((*it)) {
133                  if (this == (*it)->prevFrameProxy_.get()) {
134                      auto me = std::move((*it)->prevFrameProxy_);
135                      (*it)->prevFrameProxy_ = std::move(me->prevFrameProxy_);
136                      break;
137                  }
138                  it = &(*it)->prevFrameProxy_;
139              }
140          }
141      }
142  
GetGuard()143      RecursionGuard GetGuard()
144      {
145          return RecursionGuard(*this);
146      }
147  
FrameProxy(FrameNode * frameNode)148      explicit FrameProxy(FrameNode* frameNode) : hostNode_(frameNode)
149      {
150          prevFrameProxy_ = std::move(hostNode_->frameProxy_);
151          if (prevFrameProxy_ && !prevFrameProxy_->needResetChild_) {
152              children_ = prevFrameProxy_->children_;
153              cursor_ = children_.end();
154              if (prevFrameProxy_->cursor_ != prevFrameProxy_->children_.end()) {
155                  cursor_ = std::find_if(children_.begin(), children_.end(),
156                      [this](FrameChildNode& node) { return prevFrameProxy_->cursor_->node == node.node; });
157              }
158          }
159      }
160  
Build()161      void Build()
162      {
163          if (hostNode_ == nullptr || !children_.empty()) {
164              return;
165          }
166          totalCount_ = 0;
167          auto children = hostNode_->GetChildren();
168          int32_t startIndex = 0;
169          int32_t count = 0;
170          for (const auto& child : children) {
171              count = child->FrameCount();
172              child->SetNodeIndexOffset(startIndex, count);
173              children_.push_back({ child, startIndex, count });
174              startIndex += count;
175              totalCount_ += count;
176          }
177          cursor_ = children_.begin();
178      }
179  
AddFrameNode(const RefPtr<UINode> & UiNode,std::list<RefPtr<LayoutWrapper>> & allFrameNodeChildren,std::map<uint32_t,RefPtr<LayoutWrapper>> & partFrameNodeChildren,uint32_t & count)180      static void AddFrameNode(const RefPtr<UINode>& UiNode, std::list<RefPtr<LayoutWrapper>>& allFrameNodeChildren,
181          std::map<uint32_t, RefPtr<LayoutWrapper>>& partFrameNodeChildren, uint32_t& count)
182      {
183          auto frameNode = AceType::DynamicCast<FrameNode>(UiNode);
184          if (frameNode) {
185              allFrameNodeChildren.emplace_back(frameNode);
186              partFrameNodeChildren[count++] = frameNode;
187              return;
188          }
189          auto lazyForEachNode = AceType::DynamicCast<LazyForEachNode>(UiNode);
190          auto repeatVirtualScrollNode = AceType::DynamicCast<RepeatVirtualScrollNode>(UiNode);
191          if (lazyForEachNode) {
192              lazyForEachNode->BuildAllChildren();
193          } else if (repeatVirtualScrollNode) {
194              TAG_LOGE(AceLogTag::ACE_REPEAT, "repeatVirtualScroll not support in non scoll container!");
195          } else {
196              auto customNode = AceType::DynamicCast<CustomNode>(UiNode);
197              if (customNode) {
198                  customNode->Render();
199              }
200          }
201          for (const auto& child : UiNode->GetChildren()) {
202              auto frameNode = AceType::DynamicCast<FrameNode>(child);
203              if (frameNode) {
204                  allFrameNodeChildren.emplace_back(frameNode);
205                  partFrameNodeChildren[count++] = frameNode;
206                  continue;
207              }
208              AddFrameNode(child, allFrameNodeChildren, partFrameNodeChildren, count);
209          }
210      }
211  
GetAllFrameChildren()212      ChildrenListWithGuard GetAllFrameChildren()
213      {
214          auto guard = GetGuard();
215          if (allFrameNodeChildren_.empty()) {
216              Build();
217              uint32_t count = 0;
218              for (const auto& child : children_) {
219                  AddFrameNode(child.node, allFrameNodeChildren_, partFrameNodeChildren_, count);
220              }
221          }
222          return ChildrenListWithGuard(allFrameNodeChildren_, *this);
223      }
224  
GetCurrentFrameChildren()225      ChildrenListWithGuard GetCurrentFrameChildren()
226      {
227          auto guard = GetGuard();
228          return ChildrenListWithGuard(allFrameNodeChildren_, *this);
229      }
230  
FindFrameNodeByIndex(uint32_t index,bool needBuild,bool isCache,bool addToRenderTree)231      RefPtr<LayoutWrapper> FindFrameNodeByIndex(uint32_t index, bool needBuild, bool isCache, bool addToRenderTree)
232      {
233          while (cursor_ != children_.end()) {
234              if (cursor_->startIndex > index) {
235                  cursor_--;
236                  continue;
237              }
238  
239              if (cursor_->startIndex + cursor_->count > index) {
240                  auto frameNode = AceType::DynamicCast<FrameNode>(cursor_->node->GetFrameChildByIndex(
241                      index - cursor_->startIndex, needBuild, isCache, addToRenderTree));
242                  return frameNode;
243              }
244              cursor_++;
245              if (cursor_ == children_.end()) {
246                  cursor_ = children_.begin();
247                  return nullptr;
248              }
249          }
250          return nullptr;
251      }
252  
GetFrameNodeByIndex(uint32_t index,bool needBuild,bool isCache,bool addToRenderTree)253      RefPtr<LayoutWrapper> GetFrameNodeByIndex(uint32_t index, bool needBuild, bool isCache, bool addToRenderTree)
254      {
255          auto itor = partFrameNodeChildren_.find(index);
256          if (itor == partFrameNodeChildren_.end()) {
257              Build();
258              auto child = FindFrameNodeByIndex(index, needBuild, isCache, addToRenderTree);
259              if (child && !isCache) {
260                  partFrameNodeChildren_[index] = child;
261              }
262              return child;
263          }
264          return itor->second;
265      }
266  
267      /**
268       * @brief Find child's index in parent's map. Only works on children that are already created and recorded.
269       *
270       * @param target child LayoutWrapper
271       * @return index of children
272       */
GetChildIndex(const RefPtr<LayoutWrapper> & target) const273      int32_t GetChildIndex(const RefPtr<LayoutWrapper>& target) const
274      {
275          for (auto it : partFrameNodeChildren_) {
276              if (it.second == target) {
277                  return it.first;
278              }
279          }
280          return -1;
281      }
282  
ResetChildren(bool needResetChild=false)283      void ResetChildren(bool needResetChild = false)
284      {
285          if (inUse_) {
286              LOGF(
287                  "[%{public}d:%{public}s] reset children while in use", hostNode_->GetId(), hostNode_->GetTag().c_str());
288              if (SystemProperties::GetLayoutDetectEnabled()) {
289                  abort();
290              }
291              delayReset_ = true;
292              needResetChild_ = needResetChild;
293              hostNode_->frameProxy_ = std::make_unique<FrameProxy>(hostNode_);
294              return;
295          }
296          auto guard = GetGuard();
297          delayReset_ = false;
298          allFrameNodeChildren_.clear();
299          partFrameNodeChildren_.clear();
300          totalCount_ = 0;
301          if (needResetChild) {
302              children_.clear();
303              cursor_ = children_.begin();
304          }
305      }
306  
RemoveChildInRenderTree(uint32_t index)307      void RemoveChildInRenderTree(uint32_t index)
308      {
309          auto itor = partFrameNodeChildren_.find(index);
310          if (itor == partFrameNodeChildren_.end()) {
311              return;
312          }
313          itor->second->SetActive(false);
314          partFrameNodeChildren_.erase(itor);
315          while (cursor_ != children_.end()) {
316              if (cursor_->startIndex > index) {
317                  cursor_--;
318                  continue;
319              }
320              if (cursor_->startIndex + cursor_->count > index) {
321                  cursor_->node->DoRemoveChildInRenderTree(index - cursor_->startIndex);
322                  return;
323              }
324              cursor_++;
325              if (cursor_ == children_.end()) {
326                  cursor_ = children_.begin();
327                  return;
328              }
329          }
330      }
331  
SetActiveChildRange(int32_t start,int32_t end,int32_t cacheStart,int32_t cacheEnd,bool showCache=false)332      void SetActiveChildRange(int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd, bool showCache = false)
333      {
334          int32_t startIndex = showCache ? start - cacheStart : start;
335          int32_t endIndex = showCache ? end + cacheEnd : end;
336          for (auto itor = partFrameNodeChildren_.begin(); itor != partFrameNodeChildren_.end();) {
337              int32_t index = itor->first;
338              if ((startIndex <= endIndex && index >= startIndex && index <= endIndex) ||
339                  (startIndex > endIndex && (index <= endIndex || startIndex <= index))) {
340                  itor++;
341              } else {
342                  itor = partFrameNodeChildren_.erase(itor);
343              }
344          }
345          auto guard = GetGuard();
346          for (const auto& child : children_) {
347              child.node->DoSetActiveChildRange(
348                  start - child.startIndex, end - child.startIndex, cacheStart, cacheEnd, showCache);
349          }
350      }
351  
SetActiveChildRange(const std::optional<ActiveChildSets> & activeChildSets,const std::optional<ActiveChildRange> & activeChildRange)352      void SetActiveChildRange(
353          const std::optional<ActiveChildSets>& activeChildSets, const std::optional<ActiveChildRange>& activeChildRange)
354      {
355          if (!activeChildSets.has_value()) {
356              return;
357          }
358          for (auto itor = partFrameNodeChildren_.begin(); itor != partFrameNodeChildren_.end();) {
359              int32_t index = itor->first;
360              if (activeChildSets->activeItems.find(index) != activeChildSets->activeItems.end()) {
361                  itor++;
362              } else {
363                  itor = partFrameNodeChildren_.erase(itor);
364              }
365          }
366          auto guard = GetGuard();
367          // repeat node will use active node sets, V1 node(as lazyforeach) will still use active ndoe range.
368          for (const auto& child : children_) {
369              if (child.node->GetTag() == V2::JS_REPEAT_ETS_TAG) {
370                  child.node->DoSetActiveChildRange(
371                      activeChildSets->activeItems, activeChildSets->cachedItems, child.startIndex);
372              } else if (activeChildRange.has_value()) {
373                  child.node->DoSetActiveChildRange(activeChildRange->start - child.startIndex,
374                      activeChildRange->end - child.startIndex, activeChildRange->cacheStart, activeChildRange->cacheEnd);
375              }
376          }
377      }
378  
RecycleItemsByIndex(uint32_t start,uint32_t end)379      void RecycleItemsByIndex(uint32_t start, uint32_t end)
380      {
381          for (auto it = partFrameNodeChildren_.begin(); it != partFrameNodeChildren_.end();) {
382              if (it->first >= start && it->first < end) {
383                  it = partFrameNodeChildren_.erase(it);
384              } else {
385                  it++;
386              }
387          }
388      }
389  
RemoveAllChildInRenderTreeAfterReset()390      void RemoveAllChildInRenderTreeAfterReset()
391      {
392          Build();
393          auto guard = GetGuard();
394          for (const auto& child : children_) {
395              child.node->DoRemoveChildInRenderTree(0, true);
396          }
397      }
398  
RemoveAllChildInRenderTree()399      void RemoveAllChildInRenderTree()
400      {
401          SetAllChildrenInactive();
402          ResetChildren();
403          hostNode_->frameProxy_->RemoveAllChildInRenderTreeAfterReset();
404      }
405  
GetTotalCount()406      uint32_t GetTotalCount()
407      {
408          return totalCount_;
409      }
410  
SetAllChildrenInactive()411      void SetAllChildrenInactive()
412      {
413          auto guard = GetGuard();
414          for (const auto& child : partFrameNodeChildren_) {
415              child.second->SetActive(false);
416          }
417      }
418  
Dump()419      std::string Dump()
420      {
421          if (totalCount_ == 0) {
422              return "totalCount is 0";
423          }
424          std::string info = "FrameChildNode:[";
425          auto guard = GetGuard();
426          for (const auto& child : children_) {
427              info += std::to_string(child.node->GetId());
428              info += "-";
429              info += std::to_string(child.startIndex);
430              info += "-";
431              info += std::to_string(child.count);
432              info += ",";
433          }
434          info += "] partFrameNodeChildren:[";
435          for (const auto& child : partFrameNodeChildren_) {
436              info += std::to_string(child.second->GetHostNode()->GetId());
437              info += ",";
438          }
439          info += "] TotalCount:";
440          info += std::to_string(totalCount_);
441          return info;
442      }
443  
SetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)444      void SetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
445      {
446          auto guard = GetGuard();
447          for (const auto& child : children_) {
448              child.node->OnSetCacheCount(cacheCount, itemConstraint);
449          }
450      }
451  
452  private:
453      std::list<FrameChildNode> children_;
454      std::list<FrameChildNode>::iterator cursor_ = children_.begin();
455      std::list<RefPtr<LayoutWrapper>> allFrameNodeChildren_;
456      std::map<uint32_t, RefPtr<LayoutWrapper>> partFrameNodeChildren_;
457      std::unique_ptr<FrameProxy> prevFrameProxy_;
458      int32_t totalCount_ = 0;
459      FrameNode* hostNode_ { nullptr };
460      uint32_t inUse_ = 0;
461      bool delayReset_ = false;
462      bool needResetChild_ = false;
463  }; // namespace OHOS::Ace::NG
464  
FrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot,bool isLayoutNode)465  FrameNode::FrameNode(
466      const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot, bool isLayoutNode)
467      : UINode(tag, nodeId, isRoot), LayoutWrapper(WeakClaim(this)), pattern_(pattern)
468  {
469      isLayoutNode_ = isLayoutNode;
470      frameProxy_ = std::make_unique<FrameProxy>(this);
471      renderContext_->InitContext(IsRootNode(), pattern_->GetContextParam(), isLayoutNode);
472      paintProperty_ = pattern->CreatePaintProperty();
473      layoutProperty_ = pattern->CreateLayoutProperty();
474      eventHub_ = pattern->CreateEventHub();
475      accessibilityProperty_ = pattern->CreateAccessibilityProperty();
476      // first create make layout property dirty.
477      layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
478      layoutProperty_->SetHost(WeakClaim(this));
479      layoutSeperately_ = true;
480  }
481  
~FrameNode()482  FrameNode::~FrameNode()
483  {
484      ResetPredictNodes();
485      for (const auto& destroyCallback : destroyCallbacks_) {
486          destroyCallback();
487      }
488      for (const auto& destroyCallback : destroyCallbacksMap_) {
489          if (destroyCallback.second) {
490              destroyCallback.second();
491          }
492      }
493      if (removeCustomProperties_) {
494          removeCustomProperties_();
495          removeCustomProperties_ = nullptr;
496      }
497  
498      pattern_->DetachFromFrameNode(this);
499      if (IsOnMainTree()) {
500          OnDetachFromMainTree(false, GetContextWithCheck());
501      }
502      if (eventHub_) {
503          eventHub_->ClearOnAreaChangedInnerCallbacks();
504          if (eventHub_->HasVisibleAreaCallback(true) || eventHub_->HasVisibleAreaCallback(false)) {
505              SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::FRAMENODE_DESTROY);
506              TriggerVisibleAreaChangeCallback(0, true);
507              CleanVisibleAreaUserCallback();
508              CleanVisibleAreaInnerCallback();
509          }
510      }
511      auto pipeline = PipelineContext::GetCurrentContext();
512      if (pipeline) {
513          pipeline->RemoveOnAreaChangeNode(GetId());
514          pipeline->RemoveVisibleAreaChangeNode(GetId());
515          pipeline->ChangeMouseStyle(GetId(), MouseFormat::DEFAULT);
516          pipeline->FreeMouseStyleHoldNode(GetId());
517          pipeline->RemoveStoredNode(GetRestoreId());
518          auto dragManager = pipeline->GetDragDropManager();
519          if (dragManager) {
520              dragManager->RemoveDragFrameNode(GetId());
521              dragManager->UnRegisterDragStatusListener(GetId());
522          }
523          auto frameRateManager = pipeline->GetFrameRateManager();
524          if (frameRateManager) {
525              frameRateManager->RemoveNodeRate(GetId());
526          }
527          pipeline->RemoveChangedFrameNode(GetId());
528          pipeline->RemoveFrameNodeChangeListener(GetId());
529      }
530      FireOnNodeDestroyCallback();
531      FireFrameNodeDestructorCallback();
532  }
533  
CreateFrameNodeWithTree(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern)534  RefPtr<FrameNode> FrameNode::CreateFrameNodeWithTree(
535      const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern)
536  {
537      auto newChild = CreateFrameNode(tag, nodeId, pattern, true);
538      newChild->SetDepth(1);
539      return newChild;
540  }
541  
GetOrCreateFrameNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)542  RefPtr<FrameNode> FrameNode::GetOrCreateFrameNode(
543      const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
544  {
545      auto frameNode = GetFrameNode(tag, nodeId);
546      if (frameNode) {
547          return frameNode;
548      }
549      auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
550      return CreateFrameNode(tag, nodeId, pattern);
551  }
552  
GetOrCreateCommonNode(const std::string & tag,int32_t nodeId,bool isLayoutNode,const std::function<RefPtr<Pattern> (void)> & patternCreator)553  RefPtr<FrameNode> FrameNode::GetOrCreateCommonNode(const std::string& tag, int32_t nodeId, bool isLayoutNode,
554      const std::function<RefPtr<Pattern>(void)>& patternCreator)
555  {
556      auto commonNode = GetFrameNode(tag, nodeId);
557      if (commonNode) {
558          commonNode->isLayoutNode_ = isLayoutNode;
559          return commonNode;
560      }
561      auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
562      return CreateCommonNode(tag, nodeId, isLayoutNode, pattern);
563  }
564  
GetFrameNode(const std::string & tag,int32_t nodeId)565  RefPtr<FrameNode> FrameNode::GetFrameNode(const std::string& tag, int32_t nodeId)
566  {
567      auto frameNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(nodeId);
568      CHECK_NULL_RETURN(frameNode, nullptr);
569      if (frameNode->GetTag() != tag) {
570          ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
571          auto parent = frameNode->GetParent();
572          if (parent) {
573              parent->RemoveChild(frameNode);
574          }
575          return nullptr;
576      }
577      return frameNode;
578  }
579  
CreateFrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)580  RefPtr<FrameNode> FrameNode::CreateFrameNode(
581      const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
582  {
583      auto frameNode = MakeRefPtr<FrameNode>(tag, nodeId, pattern, isRoot);
584      ElementRegister::GetInstance()->AddUINode(frameNode);
585      frameNode->InitializePatternAndContext();
586      return frameNode;
587  }
588  
CreateCommonNode(const std::string & tag,int32_t nodeId,bool isLayoutNode,const RefPtr<Pattern> & pattern,bool isRoot)589  RefPtr<FrameNode> FrameNode::CreateCommonNode(
590      const std::string& tag, int32_t nodeId, bool isLayoutNode, const RefPtr<Pattern>& pattern, bool isRoot)
591  {
592      auto frameNode = MakeRefPtr<FrameNode>(tag, nodeId, pattern, isRoot, isLayoutNode);
593      ElementRegister::GetInstance()->AddUINode(frameNode);
594      frameNode->InitializePatternAndContext();
595      return frameNode;
596  }
597  
GetIsLayoutNode()598  bool FrameNode::GetIsLayoutNode()
599  {
600      return isLayoutNode_;
601  }
602  
GetIsFind()603  bool FrameNode::GetIsFind()
604  {
605      return isFind_;
606  }
607  
SetIsFind(bool isFind)608  void FrameNode::SetIsFind(bool isFind)
609  {
610      isFind_ = isFind;
611  }
612  
GetOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & children)613  void FrameNode::GetOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& children)
614  {
615      GenerateOneDepthVisibleFrameWithTransition(children);
616      if (overlayNode_) {
617          children.emplace_back(overlayNode_);
618      }
619  }
620  
GetOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>> & children,OffsetF & offset)621  void FrameNode::GetOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>>& children, OffsetF& offset)
622  {
623      offset += GetGeometryNode()->GetFrameOffset();
624      GenerateOneDepthVisibleFrameWithOffset(children, offset);
625      if (overlayNode_) {
626          children.emplace_back(overlayNode_);
627      }
628  }
629  
IsSupportDrawModifier()630  bool FrameNode::IsSupportDrawModifier()
631  {
632      CHECK_NULL_RETURN(pattern_, false);
633      return pattern_->IsSupportDrawModifier();
634  }
635  
ProcessOffscreenNode(const RefPtr<FrameNode> & node)636  void FrameNode::ProcessOffscreenNode(const RefPtr<FrameNode>& node)
637  {
638      CHECK_NULL_VOID(node);
639      auto task = [weak = AceType::WeakClaim(AceType::RawPtr(node))] () {
640          auto node = weak.Upgrade();
641          CHECK_NULL_VOID(node);
642          node->ProcessOffscreenTask();
643          node->MarkModifyDone();
644          node->UpdateLayoutPropertyFlag();
645          node->SetActive();
646          node->isLayoutDirtyMarked_ = true;
647          auto pipeline = node->GetContext();
648          if (pipeline) {
649              pipeline->FlushUITaskWithSingleDirtyNode(node);
650          }
651          auto predictLayoutNode = std::move(node->predictLayoutNode_);
652          for (auto& node : predictLayoutNode) {
653              auto frameNode = node.Upgrade();
654              if (frameNode && pipeline) {
655                  pipeline->FlushUITaskWithSingleDirtyNode(frameNode);
656              }
657          }
658          if (pipeline) {
659              pipeline->FlushSyncGeometryNodeTasks();
660          }
661  
662          auto paintProperty = node->GetPaintProperty<PaintProperty>();
663          auto wrapper = node->CreatePaintWrapper();
664          if (wrapper != nullptr) {
665              wrapper->FlushRender();
666          }
667          paintProperty->CleanDirty();
668          CHECK_NULL_VOID(pipeline);
669          pipeline->FlushMessages();
670          node->SetActive(false);
671      };
672      auto pipeline = node->GetContext();
673      if (pipeline && pipeline->IsLayouting()) {
674          pipeline->AddAfterLayoutTask(task);
675          return;
676      }
677      task();
678  }
679  
InitializePatternAndContext()680  void FrameNode::InitializePatternAndContext()
681  {
682      eventHub_->AttachHost(WeakClaim(this));
683      pattern_->AttachToFrameNode(WeakClaim(this));
684      accessibilityProperty_->SetHost(WeakClaim(this));
685      renderContext_->SetRequestFrame([weak = WeakClaim(this)] {
686          auto frameNode = weak.Upgrade();
687          CHECK_NULL_VOID(frameNode);
688          if (frameNode->IsOnMainTree()) {
689              auto context = frameNode->GetContext();
690              CHECK_NULL_VOID(context);
691              context->RequestFrame();
692              return;
693          }
694          frameNode->hasPendingRequest_ = true;
695      });
696      renderContext_->SetHostNode(WeakClaim(this));
697      // Initialize FocusHub
698      if (pattern_->GetFocusPattern().GetFocusType() != FocusType::DISABLE) {
699          GetOrCreateFocusHub();
700      }
701  }
702  
DumpSafeAreaInfo()703  void FrameNode::DumpSafeAreaInfo()
704  {
705      auto&& opts = layoutProperty_->GetSafeAreaExpandOpts();
706      if (opts) {
707          DumpLog::GetInstance().AddDesc(layoutProperty_->GetSafeAreaExpandOpts()
708                                             ->ToString()
709                                             .append(",hostPageId: ")
710                                             .append(std::to_string(GetPageId()).c_str()));
711      }
712      if (layoutProperty_->GetSafeAreaInsets()) {
713          DumpLog::GetInstance().AddDesc(layoutProperty_->GetSafeAreaInsets()->ToString());
714      }
715      if (SelfOrParentExpansive()) {
716          DumpLog::GetInstance().AddDesc(std::string("selfAdjust: ")
717                                             .append(geometryNode_->GetSelfAdjust().ToString().c_str())
718                                             .append(",parentAdjust: ")
719                                             .append(geometryNode_->GetParentAdjust().ToString().c_str()));
720      }
721      CHECK_NULL_VOID(GetTag() == V2::PAGE_ETS_TAG);
722      auto pipeline = GetContext();
723      CHECK_NULL_VOID(pipeline);
724      auto manager = pipeline->GetSafeAreaManager();
725      CHECK_NULL_VOID(manager);
726      DumpLog::GetInstance().AddDesc(std::string("ignoreSafeArea: ")
727                                         .append(std::to_string(manager->IsIgnoreAsfeArea()))
728                                         .append(std::string(", isNeedAvoidWindow: ").c_str())
729                                         .append(std::to_string(manager->IsNeedAvoidWindow()))
730                                         .append(std::string(", isFullScreen: ").c_str())
731                                         .append(std::to_string(manager->IsFullScreen()))
732                                         .append(std::string(", isKeyboardAvoidMode").c_str())
733                                         .append(std::to_string(static_cast<int32_t>(manager->GetKeyBoardAvoidMode())))
734                                         .append(std::string(", isUseCutout").c_str())
735                                         .append(std::to_string(pipeline->GetUseCutout())));
736  }
737  
DumpAlignRulesInfo()738  void FrameNode::DumpAlignRulesInfo()
739  {
740      auto& flexItemProperties = layoutProperty_->GetFlexItemProperty();
741      CHECK_NULL_VOID(flexItemProperties);
742      auto rulesToString = flexItemProperties->AlignRulesToString();
743      CHECK_NULL_VOID(!rulesToString.empty());
744      DumpLog::GetInstance().AddDesc(std::string("AlignRules: ").append(rulesToString));
745  }
746  
DumpExtensionHandlerInfo()747  void FrameNode::DumpExtensionHandlerInfo()
748  {
749      if (!extensionHandler_) {
750          return;
751      }
752      DumpLog::GetInstance().AddDesc(std::string("ExtensionHandler: HasCustomerMeasure: ")
753                                         .append(extensionHandler_->HasCustomerMeasure() ? "true" : "false")
754                                         .append(", HasCustomerLayout: ")
755                                         .append(extensionHandler_->HasCustomerLayout() ? "true" : "false"));
756  }
757  
DumpCommonInfo()758  void FrameNode::DumpCommonInfo()
759  {
760      DumpLog::GetInstance().AddDesc(std::string("FrameRect: ").append(geometryNode_->GetFrameRect().ToString()));
761      DumpLog::GetInstance().AddDesc(
762          std::string("PaintRect without transform: ").append(renderContext_->GetPaintRectWithoutTransform().ToString()));
763      if (renderContext_->GetBackgroundColor()->ColorToString().compare("#00000000") != 0) {
764          DumpLog::GetInstance().AddDesc(
765              std::string("BackgroundColor: ").append(renderContext_->GetBackgroundColor()->ColorToString()));
766      }
767      if (geometryNode_->GetParentLayoutConstraint().has_value()) {
768          DumpLog::GetInstance().AddDesc(std::string("ParentLayoutConstraint: ")
769              .append(geometryNode_->GetParentLayoutConstraint().value().ToString()));
770      }
771      DumpLog::GetInstance().AddDesc(std::string("top: ")
772          .append(std::to_string(GetOffsetRelativeToWindow().GetY()))
773          .append(" left: ")
774          .append(std::to_string(GetOffsetRelativeToWindow().GetX())));
775      if (static_cast<int32_t>(IsActive()) != 1) {
776          DumpLog::GetInstance().AddDesc(
777              std::string("Active: ").append(std::to_string(static_cast<int32_t>(IsActive()))));
778      }
779      if (IsFreeze()) {
780          DumpLog::GetInstance().AddDesc(std::string("Freeze: 1"));
781      }
782      if (static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)) != 0) {
783          DumpLog::GetInstance().AddDesc(std::string("Visible: ")
784                                             .append(std::to_string(static_cast<int32_t>(
785                                                 layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)))));
786      }
787      if (layoutProperty_->GetPaddingProperty()) {
788          DumpLog::GetInstance().AddDesc(
789              std::string("Padding: ").append(layoutProperty_->GetPaddingProperty()->ToString().c_str()));
790      }
791      if (layoutProperty_->GetSafeAreaPaddingProperty()) {
792          DumpLog::GetInstance().AddDesc(std::string("SafeArea Padding: ")
793                                             .append(layoutProperty_->GetSafeAreaPaddingProperty()->ToString().c_str()));
794      }
795      if (layoutProperty_->GetBorderWidthProperty()) {
796          DumpLog::GetInstance().AddDesc(
797              std::string("Border: ").append(layoutProperty_->GetBorderWidthProperty()->ToString().c_str()));
798      }
799      if (layoutProperty_->GetMarginProperty()) {
800          DumpLog::GetInstance().AddDesc(
801              std::string("Margin: ").append(layoutProperty_->GetMarginProperty()->ToString().c_str()));
802      }
803      if (layoutProperty_->GetLayoutRect()) {
804          DumpLog::GetInstance().AddDesc(
805              std::string("LayoutRect: ").append(layoutProperty_->GetLayoutRect().value().ToString().c_str()));
806      }
807      DumpExtensionHandlerInfo();
808      DumpSafeAreaInfo();
809      if (layoutProperty_->GetCalcLayoutConstraint()) {
810          DumpLog::GetInstance().AddDesc(std::string("User defined constraint: ")
811                                             .append(layoutProperty_->GetCalcLayoutConstraint()->ToString().c_str()));
812      }
813      if (!propInspectorId_->empty()) {
814          DumpLog::GetInstance().AddDesc(std::string("compid: ").append(propInspectorId_.value_or("")));
815      }
816      if (layoutProperty_->GetPaddingProperty() || layoutProperty_->GetBorderWidthProperty() ||
817          layoutProperty_->GetMarginProperty() || layoutProperty_->GetCalcLayoutConstraint()) {
818          DumpLog::GetInstance().AddDesc(
819              std::string("ContentConstraint: ")
820                  .append(layoutProperty_->GetContentLayoutConstraint().has_value()
821                              ? layoutProperty_->GetContentLayoutConstraint().value().ToString()
822                              : "NA"));
823      }
824      if (GetTag() == V2::ROOT_ETS_TAG) {
825          auto pipeline = GetContext();
826          CHECK_NULL_VOID(pipeline);
827          DumpLog::GetInstance().AddDesc(std::string("dpi: ").append(std::to_string(pipeline->GetDensity())));
828      }
829      DumpAlignRulesInfo();
830      DumpDragInfo();
831      DumpOverlayInfo();
832      if (frameProxy_->Dump().compare("totalCount is 0") != 0) {
833          DumpLog::GetInstance().AddDesc(std::string("FrameProxy: ").append(frameProxy_->Dump().c_str()));
834      }
835      if (isRemoving_) {
836          DumpLog::GetInstance().AddDesc(std::string("IsRemoving: True"));
837      }
838  }
839  
DumpDragInfo()840  void FrameNode::DumpDragInfo()
841  {
842      DumpLog::GetInstance().AddDesc("------------start print dragInfo");
843      DumpLog::GetInstance().AddDesc(std::string("Draggable: ")
844                                         .append(draggable_ ? "true" : "false")
845                                         .append(" UserSet: ")
846                                         .append(userSet_ ? "true" : "false")
847                                         .append(" CustomerSet: ")
848                                         .append(customerSet_ ? "true" : "false"));
849      auto dragPreviewStr =
850          std::string("DragPreview: Has customNode: ").append(dragPreviewInfo_.customNode ? "YES" : "NO");
851      dragPreviewStr.append(" Has pixelMap: ").append(dragPreviewInfo_.pixelMap ? "YES" : "NO");
852      dragPreviewStr.append(" extraInfo: ").append(dragPreviewInfo_.extraInfo.c_str());
853      dragPreviewStr.append(" inspectorId: ").append(dragPreviewInfo_.inspectorId.c_str());
854      DumpLog::GetInstance().AddDesc(dragPreviewStr);
855      auto eventHub = GetEventHub<EventHub>();
856      DumpLog::GetInstance().AddDesc(std::string("Event: ")
857                                         .append("OnDragStart: ")
858                                         .append(eventHub->HasOnDragStart() ? "YES" : "NO")
859                                         .append(" OnDragEnter: ")
860                                         .append(eventHub->HasOnDragEnter() ? "YES" : "NO")
861                                         .append(" OnDragLeave: ")
862                                         .append(eventHub->HasOnDragLeave() ? "YES" : "NO")
863                                         .append(" OnDragMove: ")
864                                         .append(eventHub->HasOnDragMove() ? "YES" : "NO")
865                                         .append(" OnDrop: ")
866                                         .append(eventHub->HasOnDrop() ? "YES" : "NO")
867                                         .append(" OnDragEnd: ")
868                                         .append(eventHub->HasOnDragEnd() ? "YES" : "NO"));
869      DumpLog::GetInstance().AddDesc(std::string("DefaultOnDragStart: ")
870                                         .append(eventHub->HasDefaultOnDragStart() ? "YES" : "NO")
871                                         .append(" CustomerOnDragEnter: ")
872                                         .append(eventHub->HasCustomerOnDragEnter() ? "YES" : "NO")
873                                         .append(" CustomerOnDragLeave: ")
874                                         .append(eventHub->HasCustomerOnDragLeave() ? "YES" : "NO")
875                                         .append(" CustomerOnDragMove: ")
876                                         .append(eventHub->HasCustomerOnDragMove() ? "YES" : "NO")
877                                         .append(" CustomerOnDrop: ")
878                                         .append(eventHub->HasCustomerOnDrop() ? "YES" : "NO")
879                                         .append(" CustomerOnDragEnd: ")
880                                         .append(eventHub->HasCustomerOnDragEnd() ? "YES" : "NO"));
881      DumpLog::GetInstance().AddDesc("------------end print dragInfo");
882  }
883  
DumpOnSizeChangeInfo()884  void FrameNode::DumpOnSizeChangeInfo()
885  {
886      for (auto it = onSizeChangeDumpInfos.rbegin(); it != onSizeChangeDumpInfos.rend(); ++it) {
887          DumpLog::GetInstance().AddDesc(std::string("onSizeChange Time: ")
888                                             .append(ConvertTimestampToStr(it->onSizeChangeTimeStamp))
889                                             .append(" lastFrameRect: ")
890                                             .append(it->lastFrameRect.ToString())
891                                             .append(" currFrameRect: ")
892                                             .append(it->currFrameRect.ToString()));
893      }
894  }
895  
DumpOverlayInfo()896  void FrameNode::DumpOverlayInfo()
897  {
898      if (!layoutProperty_->IsOverlayNode()) {
899          return;
900      }
901      DumpLog::GetInstance().AddDesc(std::string("IsOverlayNode: ").append(std::string("true")));
902      Dimension offsetX, offsetY;
903      layoutProperty_->GetOverlayOffset(offsetX, offsetY);
904      DumpLog::GetInstance().AddDesc(
905          std::string("OverlayOffset: ").append(offsetX.ToString()).append(std::string(", ")).append(offsetY.ToString()));
906  }
907  
DumpSimplifyCommonInfo(std::unique_ptr<JsonValue> & json)908  void FrameNode::DumpSimplifyCommonInfo(std::unique_ptr<JsonValue>& json)
909  {
910      if (geometryNode_) {
911          if (geometryNode_->GetFrameRect() != RectF(0.0, 0.0, 0.0, 0.0)) {
912              json->Put("FrameRect", geometryNode_->GetFrameRect().ToString().c_str());
913          }
914          if (geometryNode_->GetParentLayoutConstraint().has_value()) {
915              json->Put("ParentLayoutConstraint", geometryNode_->GetParentLayoutConstraint().value().ToString().c_str());
916          }
917          auto offset = GetOffsetRelativeToWindow();
918          if (offset != OffsetF(0.0, 0.0)) {
919              std::stringstream stream;
920              stream << std::fixed << std::setprecision(DEFAULT_PRECISION) << offset.GetX() << "," << offset.GetY();
921              json->Put("Offset", stream.str().c_str());
922          }
923      }
924      if (renderContext_) {
925          if (renderContext_->GetPaintRectWithoutTransform() != RectF(0.0, 0.0, 0.0, 0.0)) {
926              json->Put("PaintRectWithoutTransform", renderContext_->GetPaintRectWithoutTransform().ToString().c_str());
927          }
928          if (renderContext_->GetBackgroundColor() &&
929              renderContext_->GetBackgroundColor()->ColorToString().compare("#00000000") != 0) {
930              json->Put("BackgroundColor", renderContext_->GetBackgroundColor()->ColorToString().c_str());
931          }
932          if (!NearZero(renderContext_->GetZIndexValue(ZINDEX_DEFAULT_VALUE))) {
933              json->Put("ZIndex: ", renderContext_->GetZIndexValue(ZINDEX_DEFAULT_VALUE));
934          }
935      }
936      if (layoutProperty_) {
937          VisibleType visible = layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE);
938          if (visible != VisibleType::VISIBLE) {
939              json->Put("Visible", static_cast<int32_t>(visible));
940          }
941          DumpPadding(layoutProperty_->GetPaddingProperty(), std::string("Padding"), json);
942          DumpBorder(layoutProperty_->GetBorderWidthProperty(), std::string("Border"), json);
943          DumpPadding(layoutProperty_->GetMarginProperty(), std::string("Margin"), json);
944          if (layoutProperty_->GetLayoutRect()) {
945              json->Put("LayoutRect", layoutProperty_->GetLayoutRect().value().ToString().c_str());
946          }
947          if (layoutProperty_->GetCalcLayoutConstraint()) {
948              json->Put("UserDefinedConstraint", layoutProperty_->GetCalcLayoutConstraint()->ToString().c_str());
949          }
950          if (layoutProperty_->GetPaddingProperty() || layoutProperty_->GetBorderWidthProperty() ||
951              layoutProperty_->GetMarginProperty() || layoutProperty_->GetCalcLayoutConstraint()) {
952              if (layoutProperty_->GetContentLayoutConstraint().has_value()) {
953                  json->Put("ContentConstraint",
954                      layoutProperty_->GetContentLayoutConstraint().value().ToString().c_str());
955              }
956          }
957      }
958  }
959  
DumpPadding(const std::unique_ptr<NG::PaddingProperty> & padding,std::string label,std::unique_ptr<JsonValue> & json)960  void FrameNode::DumpPadding(const std::unique_ptr<NG::PaddingProperty>& padding, std::string label,
961      std::unique_ptr<JsonValue>& json)
962  {
963      CHECK_NULL_VOID(padding);
964      NG::CalcLength defaultValue = NG::CalcLength(
965          Dimension(0, padding->left.value_or(CalcLength()).GetDimension().Unit()));
966      if (padding->left.value_or(defaultValue) != defaultValue || padding->right.value_or(defaultValue) != defaultValue ||
967          padding->top.value_or(defaultValue) != defaultValue || padding->bottom.value_or(defaultValue) != defaultValue) {
968          json->Put(label.c_str(), padding->ToString().c_str());
969      }
970  }
971  
DumpBorder(const std::unique_ptr<NG::BorderWidthProperty> & border,std::string label,std::unique_ptr<JsonValue> & json)972  void FrameNode::DumpBorder(const std::unique_ptr<NG::BorderWidthProperty>& border, std::string label,
973      std::unique_ptr<JsonValue>& json)
974  {
975      CHECK_NULL_VOID(border);
976      Dimension defaultValue(0, border->leftDimen.value_or(Dimension()).Unit());
977      if (border->leftDimen.value_or(defaultValue) != defaultValue ||
978          border->rightDimen.value_or(defaultValue) != defaultValue ||
979          border->topDimen.value_or(defaultValue) != defaultValue ||
980          border->bottomDimen.value_or(defaultValue) != defaultValue) {
981          json->Put(label.c_str(), border->ToString().c_str());
982      }
983  }
984  
DumpSimplifySafeAreaInfo(std::unique_ptr<JsonValue> & json)985  void FrameNode::DumpSimplifySafeAreaInfo(std::unique_ptr<JsonValue>& json)
986  {
987      if (layoutProperty_) {
988          auto&& opts = layoutProperty_->GetSafeAreaExpandOpts();
989          if (opts && opts->type != NG::SAFE_AREA_TYPE_NONE && opts->edges != NG::SAFE_AREA_EDGE_NONE) {
990              json->Put("SafeAreaExpandOpts", opts->ToString().c_str());
991          }
992          if (layoutProperty_->GetSafeAreaInsets()) {
993              json->Put("SafeAreaInsets", layoutProperty_->GetSafeAreaInsets()->ToString().c_str());
994          }
995      }
996      if (SelfOrParentExpansive()) {
997          if (geometryNode_) {
998              RectF defaultValue(0.0, 0.0, 0.0, 0.0);
999              auto rect = geometryNode_->GetSelfAdjust();
1000              auto parentRect = geometryNode_->GetParentAdjust();
1001              if (rect != defaultValue) {
1002                  json->Put("SelfAdjust", rect.ToString().c_str());
1003              }
1004              if (parentRect != defaultValue) {
1005                  json->Put("ParentSelfAdjust", parentRect.ToString().c_str());
1006              }
1007          }
1008          CHECK_EQUAL_VOID(GetTag(), V2::PAGE_ETS_TAG);
1009          auto pipeline = GetContext();
1010          CHECK_NULL_VOID(pipeline);
1011          auto manager = pipeline->GetSafeAreaManager();
1012          CHECK_NULL_VOID(manager);
1013          if (!manager->IsIgnoreAsfeArea()) {
1014              json->Put("IgnoreSafeArea", manager->IsIgnoreAsfeArea());
1015          }
1016          if (!manager->IsNeedAvoidWindow()) {
1017              json->Put("IsNeedAvoidWindow", manager->IsNeedAvoidWindow());
1018          }
1019          if (!manager->IsFullScreen()) {
1020              json->Put("IsFullScreen", manager->IsFullScreen());
1021          }
1022          if (!manager->KeyboardSafeAreaEnabled()) {
1023              json->Put("IsKeyboardAvoidMode", static_cast<int32_t>(manager->GetKeyBoardAvoidMode()));
1024          }
1025          if (!pipeline->GetUseCutout()) {
1026              json->Put("IsUseCutout", pipeline->GetUseCutout());
1027          }
1028      }
1029  }
1030  
DumpSimplifyOverlayInfo(std::unique_ptr<JsonValue> & json)1031  void FrameNode::DumpSimplifyOverlayInfo(std::unique_ptr<JsonValue>& json)
1032  {
1033      if (layoutProperty_ || !layoutProperty_->IsOverlayNode()) {
1034          return;
1035      }
1036      json->Put("IsOverlayNode", true);
1037      Dimension offsetX;
1038      Dimension offsetY;
1039      layoutProperty_->GetOverlayOffset(offsetX, offsetY);
1040      json->Put("OverlayOffset", (offsetX.ToString() + "," + offsetY.ToString()).c_str());
1041  }
1042  
DumpSimplifyInfo(std::unique_ptr<JsonValue> & json)1043  void FrameNode::DumpSimplifyInfo(std::unique_ptr<JsonValue>& json)
1044  {
1045      CHECK_NULL_VOID(json);
1046      DumpSimplifyCommonInfo(json);
1047      DumpSimplifySafeAreaInfo(json);
1048      DumpSimplifyOverlayInfo(json);
1049      if (pattern_ && GetTag() == V2::UI_EXTENSION_COMPONENT_TAG) {
1050          pattern_->DumpInfo(json);
1051      }
1052      if (renderContext_) {
1053          auto renderContextJson = JsonUtil::Create();
1054          renderContext_->DumpSimplifyInfo(renderContextJson);
1055          json->PutRef("RenderContext", std::move(renderContextJson));
1056      }
1057  }
1058  
DumpInfo()1059  void FrameNode::DumpInfo()
1060  {
1061      DumpCommonInfo();
1062      DumpOnSizeChangeInfo();
1063      if (pattern_) {
1064          pattern_->DumpInfo();
1065      }
1066      if (renderContext_) {
1067          renderContext_->DumpInfo();
1068      }
1069  }
1070  
DumpAdvanceInfo()1071  void FrameNode::DumpAdvanceInfo()
1072  {
1073      DumpCommonInfo();
1074      DumpOnSizeChangeInfo();
1075      if (pattern_) {
1076          pattern_->DumpInfo();
1077          pattern_->DumpAdvanceInfo();
1078      }
1079      if (renderContext_) {
1080          renderContext_->DumpInfo();
1081          renderContext_->DumpAdvanceInfo();
1082      }
1083  }
1084  
DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap,bool needsRecordData)1085  void FrameNode::DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap, bool needsRecordData)
1086  {
1087      if (pattern_) {
1088          pattern_->DumpViewDataPageNode(viewDataWrap, needsRecordData);
1089      }
1090  }
1091  
CheckAutoSave()1092  bool FrameNode::CheckAutoSave()
1093  {
1094      if (pattern_) {
1095          return pattern_->CheckAutoSave();
1096      }
1097      return false;
1098  }
1099  
MouseToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1100  void FrameNode::MouseToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1101  {
1102      std::string hoverEffect = "HoverEffect.Auto";
1103      /* no fixed attr below, just return */
1104      if (filter.IsFastFilter()) {
1105          return;
1106      }
1107      auto inputEventHub = GetOrCreateInputEventHub();
1108      if (inputEventHub) {
1109          hoverEffect = inputEventHub->GetHoverEffectStr();
1110      }
1111      json->PutExtAttr("hoverEffect", hoverEffect.c_str(), filter);
1112  }
1113  
TouchToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1114  void FrameNode::TouchToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1115  {
1116      bool touchable = true;
1117      bool monopolizeEvents = false;
1118      std::string hitTestMode = "HitTestMode.Default";
1119      /* no fixed attr below, just return */
1120      if (filter.IsFastFilter()) {
1121          return;
1122      }
1123      auto gestureEventHub = GetOrCreateGestureEventHub();
1124      std::vector<DimensionRect> responseRegion;
1125      std::vector<DimensionRect> mouseResponseRegion;
1126      if (gestureEventHub) {
1127          touchable = gestureEventHub->GetTouchable();
1128          hitTestMode = gestureEventHub->GetHitTestModeStr();
1129          responseRegion = gestureEventHub->GetResponseRegion();
1130          mouseResponseRegion = gestureEventHub->GetMouseResponseRegion();
1131          monopolizeEvents = gestureEventHub->GetMonopolizeEvents();
1132      }
1133      json->PutExtAttr("touchable", touchable, filter);
1134      json->PutExtAttr("hitTestBehavior", hitTestMode.c_str(), filter);
1135      json->PutExtAttr("monopolizeEvents", monopolizeEvents, filter);
1136      auto jsArr = JsonUtil::CreateArray(true);
1137      for (int32_t i = 0; i < static_cast<int32_t>(responseRegion.size()); ++i) {
1138          auto iStr = std::to_string(i);
1139          jsArr->Put(iStr.c_str(), responseRegion[i].ToJsonString().c_str());
1140      }
1141      json->PutExtAttr("responseRegion", jsArr, filter);
1142      for (int32_t i = 0; i < static_cast<int32_t>(mouseResponseRegion.size()); ++i) {
1143          auto iStr = std::to_string(i);
1144          jsArr->Put(iStr.c_str(), mouseResponseRegion[i].ToJsonString().c_str());
1145      }
1146      json->PutExtAttr("mouseResponseRegion", jsArr, filter);
1147  }
1148  
GeometryNodeToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1149  void FrameNode::GeometryNodeToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1150  {
1151      bool hasIdealWidth = false;
1152      bool hasIdealHeight = false;
1153      /* no fixed attr below, just return */
1154      if (filter.IsFastFilter()) {
1155          return;
1156      }
1157      if (layoutProperty_ && layoutProperty_->GetCalcLayoutConstraint()) {
1158          auto selfIdealSize = layoutProperty_->GetCalcLayoutConstraint()->selfIdealSize;
1159          hasIdealWidth = selfIdealSize.has_value() && selfIdealSize.value().Width().has_value();
1160          hasIdealHeight = selfIdealSize.has_value() && selfIdealSize.value().Height().has_value();
1161      }
1162  
1163      auto jsonSize = json->GetValue("size");
1164      if (!hasIdealWidth) {
1165          auto idealWidthVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Width()).ConvertToVp());
1166          auto widthStr = (idealWidthVpStr.substr(0, idealWidthVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP);
1167          json->PutExtAttr("width", widthStr.c_str(), filter);
1168          if (jsonSize) {
1169              jsonSize->Put("width", widthStr.c_str());
1170          }
1171      }
1172  
1173      if (!hasIdealHeight) {
1174          auto idealHeightVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Height()).ConvertToVp());
1175          auto heightStr = (idealHeightVpStr.substr(0, idealHeightVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP);
1176          json->PutExtAttr("height", heightStr.c_str(), filter);
1177          if (jsonSize) {
1178              jsonSize->Put("height", heightStr.c_str());
1179          }
1180      }
1181  }
1182  
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1183  void FrameNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1184  {
1185      if (renderContext_) {
1186          renderContext_->ToJsonValue(json, filter);
1187      }
1188      // scrollable in AccessibilityProperty
1189      ACE_PROPERTY_TO_JSON_VALUE(accessibilityProperty_, AccessibilityProperty);
1190      ACE_PROPERTY_TO_JSON_VALUE(layoutProperty_, LayoutProperty);
1191      ACE_PROPERTY_TO_JSON_VALUE(paintProperty_, PaintProperty);
1192      ACE_PROPERTY_TO_JSON_VALUE(pattern_, Pattern);
1193      if (eventHub_) {
1194          eventHub_->ToJsonValue(json, filter);
1195      }
1196      FocusHub::ToJsonValue(GetFocusHub(), json, filter);
1197      MouseToJsonValue(json, filter);
1198      TouchToJsonValue(json, filter);
1199      if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1200  #if defined(PREVIEW)
1201          GeometryNodeToJsonValue(json, filter);
1202  #endif
1203      } else {
1204          GeometryNodeToJsonValue(json, filter);
1205      }
1206      json->PutFixedAttr("id", propInspectorId_.value_or("").c_str(), filter, FIXED_ATTR_ID);
1207  }
1208  
FromJson(const std::unique_ptr<JsonValue> & json)1209  void FrameNode::FromJson(const std::unique_ptr<JsonValue>& json)
1210  {
1211      if (renderContext_) {
1212          renderContext_->FromJson(json);
1213      }
1214      accessibilityProperty_->FromJson(json);
1215      layoutProperty_->FromJson(json);
1216      paintProperty_->FromJson(json);
1217      pattern_->FromJson(json);
1218      if (eventHub_) {
1219          eventHub_->FromJson(json);
1220      }
1221  }
1222  
UpdateGeometryTransition()1223  void FrameNode::UpdateGeometryTransition()
1224  {
1225      const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
1226      if (geometryTransition) {
1227          layoutProperty_->UpdateGeometryTransition("");
1228          layoutProperty_->UpdateGeometryTransition(geometryTransition->GetId());
1229          MarkDirtyNode();
1230      }
1231      auto children = GetChildren();
1232      for (const auto& child : children) {
1233          child->UpdateGeometryTransition();
1234      }
1235  }
1236  
TriggerRsProfilerNodeMountCallbackIfExist()1237  void FrameNode::TriggerRsProfilerNodeMountCallbackIfExist()
1238  {
1239  #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
1240      CHECK_NULL_VOID(renderContext_);
1241      auto callback = LayoutInspector::GetRsProfilerNodeMountCallback();
1242      if (callback) {
1243          FrameNodeInfo info { renderContext_->GetNodeId(), GetId(), GetTag(), GetDebugLine() };
1244          callback(info);
1245      }
1246  #endif
1247  }
1248  
OnAttachToMainTree(bool recursive)1249  void FrameNode::OnAttachToMainTree(bool recursive)
1250  {
1251      TriggerRsProfilerNodeMountCallbackIfExist();
1252      eventHub_->FireOnAttach();
1253      eventHub_->FireOnAppear();
1254      renderContext_->OnNodeAppear(recursive);
1255      pattern_->OnAttachToMainTree();
1256  
1257      if (isActive_ && SystemProperties::GetDeveloperModeOn()) {
1258          PaintDebugBoundary(SystemProperties::GetDebugBoundaryEnabled());
1259      }
1260      // node may have been measured before AttachToMainTree
1261      if (geometryNode_->GetParentLayoutConstraint().has_value() && !UseOffscreenProcess()) {
1262          layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE_SELF);
1263      }
1264      UINode::OnAttachToMainTree(recursive);
1265      auto context = GetContext();
1266      CHECK_NULL_VOID(context);
1267      auto predictLayoutNode = std::move(predictLayoutNode_);
1268      for (auto& node : predictLayoutNode) {
1269          auto frameNode = node.Upgrade();
1270          if (frameNode && frameNode->isLayoutDirtyMarked_) {
1271              context->AddDirtyLayoutNode(frameNode);
1272          }
1273      }
1274  
1275      if (isPropertyDiffMarked_) {
1276          context->AddDirtyPropertyNode(Claim(this));
1277      }
1278      if (!hasPendingRequest_) {
1279          return;
1280      }
1281      context->RequestFrame();
1282      hasPendingRequest_ = false;
1283  }
1284  
OnAttachToBuilderNode(NodeStatus nodeStatus)1285  void FrameNode::OnAttachToBuilderNode(NodeStatus nodeStatus)
1286  {
1287      pattern_->OnAttachToBuilderNode(nodeStatus);
1288  }
1289  
RenderCustomChild(int64_t deadline)1290  bool FrameNode::RenderCustomChild(int64_t deadline)
1291  {
1292      if (!pattern_->RenderCustomChild(deadline)) {
1293          return false;
1294      }
1295      return UINode::RenderCustomChild(deadline);
1296  }
1297  
OnConfigurationUpdate(const ConfigurationChange & configurationChange)1298  void FrameNode::OnConfigurationUpdate(const ConfigurationChange& configurationChange)
1299  {
1300      if (configurationChange.languageUpdate) {
1301          pattern_->OnLanguageConfigurationUpdate();
1302          MarkModifyDone();
1303          MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1304      }
1305      if (configurationChange.colorModeUpdate) {
1306          pattern_->OnColorConfigurationUpdate();
1307          if (colorModeUpdateCallback_) {
1308              // copy it first in case of changing colorModeUpdateCallback_ in the callback
1309              auto cb = colorModeUpdateCallback_;
1310              cb();
1311          }
1312          MarkModifyDone();
1313          MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1314      }
1315      if (configurationChange.directionUpdate) {
1316          pattern_->OnDirectionConfigurationUpdate();
1317          MarkModifyDone();
1318          MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1319      }
1320      if (configurationChange.dpiUpdate) {
1321          pattern_->OnDpiConfigurationUpdate();
1322          MarkModifyDone();
1323          MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1324      }
1325      if (configurationChange.fontUpdate) {
1326          pattern_->OnFontConfigurationUpdate();
1327          MarkModifyDone();
1328          MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1329      }
1330      if (configurationChange.iconUpdate) {
1331          pattern_->OnIconConfigurationUpdate();
1332          MarkModifyDone();
1333          MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1334      }
1335      if (configurationChange.skinUpdate) {
1336          MarkModifyDone();
1337          MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1338      }
1339      if (configurationChange.fontScaleUpdate) {
1340          pattern_->OnFontScaleConfigurationUpdate();
1341          MarkModifyDone();
1342          MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1343      }
1344      NotifyConfigurationChangeNdk(configurationChange);
1345  }
1346  
NotifyConfigurationChangeNdk(const ConfigurationChange & configurationChange)1347  void FrameNode::NotifyConfigurationChangeNdk(const ConfigurationChange& configurationChange)
1348  {
1349      if (ndkColorModeUpdateCallback_ && configurationChange.colorModeUpdate &&
1350          colorMode_ != SystemProperties::GetColorMode()) {
1351          auto colorModeChange = ndkColorModeUpdateCallback_;
1352          colorModeChange(SystemProperties::GetColorMode() == ColorMode::DARK);
1353          colorMode_ = SystemProperties::GetColorMode();
1354      }
1355  
1356      if (ndkFontUpdateCallback_ && (configurationChange.fontScaleUpdate || configurationChange.fontWeightScaleUpdate)) {
1357          auto fontChangeCallback = ndkFontUpdateCallback_;
1358          auto pipeline = GetContextWithCheck();
1359          CHECK_NULL_VOID(pipeline);
1360          fontChangeCallback(pipeline->GetFontScale(), pipeline->GetFontWeightScale());
1361      }
1362  }
1363  
NotifyVisibleChange(VisibleType preVisibility,VisibleType currentVisibility)1364  void FrameNode::NotifyVisibleChange(VisibleType preVisibility, VisibleType currentVisibility)
1365  {
1366      if ((preVisibility != currentVisibility &&
1367              (preVisibility == VisibleType::GONE || currentVisibility == VisibleType::GONE)) &&
1368          SelfExpansive()) {
1369          MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1370      }
1371      pattern_->OnVisibleChange(currentVisibility == VisibleType::VISIBLE);
1372      UpdateChildrenVisible(preVisibility, currentVisibility);
1373  }
1374  
TryVisibleChangeOnDescendant(VisibleType preVisibility,VisibleType currentVisibility)1375  void FrameNode::TryVisibleChangeOnDescendant(VisibleType preVisibility, VisibleType currentVisibility)
1376  {
1377      auto layoutProperty = GetLayoutProperty();
1378      if (layoutProperty && layoutProperty->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE) {
1379          return;
1380      }
1381      NotifyVisibleChange(preVisibility, currentVisibility);
1382  }
1383  
OnDetachFromMainTree(bool recursive,PipelineContext * context)1384  void FrameNode::OnDetachFromMainTree(bool recursive, PipelineContext* context)
1385  {
1386      auto focusHub = GetFocusHub();
1387      if (focusHub) {
1388          auto focusView = focusHub->GetFirstChildFocusView();
1389          if (focusView) {
1390              focusView->FocusViewClose(true);
1391          }
1392          focusHub->RemoveSelf();
1393      }
1394      eventHub_->FireOnDetach();
1395      pattern_->OnDetachFromMainTree();
1396      eventHub_->FireOnDisappear();
1397      CHECK_NULL_VOID(renderContext_);
1398      renderContext_->OnNodeDisappear(recursive);
1399      if (context) {
1400          const auto& safeAreaManager = context->GetSafeAreaManager();
1401          if (safeAreaManager) {
1402              safeAreaManager->RemoveRestoreNode(WeakClaim(this));
1403          }
1404      }
1405  }
1406  
SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper> & dirty)1407  void FrameNode::SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper>& dirty)
1408  {
1409      CHECK_NULL_VOID(dirty);
1410  
1411      // update new layout constrain.
1412      layoutProperty_->UpdateLayoutConstraint(dirty->GetLayoutProperty());
1413  
1414      // active change flag judge.
1415      SetActive(dirty->IsActive());
1416      if (!isActive_) {
1417          return;
1418      }
1419  
1420      // update layout size.
1421      bool frameSizeChange = geometryNode_->GetFrameSize() != dirty->GetGeometryNode()->GetFrameSize();
1422      bool frameOffsetChange = geometryNode_->GetFrameOffset() != dirty->GetGeometryNode()->GetFrameOffset();
1423      bool contentSizeChange = geometryNode_->GetContentSize() != dirty->GetGeometryNode()->GetContentSize();
1424      bool contentOffsetChange = geometryNode_->GetContentOffset() != dirty->GetGeometryNode()->GetContentOffset();
1425  
1426      SetGeometryNode(dirty->GetGeometryNode());
1427  
1428      const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
1429      if (geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this))) {
1430          geometryTransition->DidLayout(dirty);
1431          if (geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
1432              isLayoutDirtyMarked_ = true;
1433          }
1434      } else if (frameSizeChange || frameOffsetChange || HasPositionProp() ||
1435                 (pattern_->GetContextParam().has_value() && contentSizeChange)) {
1436          renderContext_->SyncGeometryProperties(RawPtr(dirty->GetGeometryNode()));
1437      }
1438  
1439      // clean layout flag.
1440      layoutProperty_->CleanDirty();
1441      DirtySwapConfig config { frameSizeChange, frameOffsetChange, contentSizeChange, contentOffsetChange };
1442      // check if need to paint content.
1443      auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
1444      CHECK_NULL_VOID(layoutAlgorithmWrapper);
1445      config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure() || dirty->SkipMeasureContent();
1446      config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
1447      if ((config.skipMeasure == false) && (config.skipLayout == false) && GetInspectorId().has_value()) {
1448          auto pipeline = GetContext();
1449          CHECK_NULL_VOID(pipeline);
1450          pipeline->OnLayoutCompleted(GetInspectorId()->c_str());
1451      }
1452      auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(dirty, config);
1453      needRerender = needRerender || pattern_->OnDirtyLayoutWrapperSwap(dirty, config.skipMeasure, config.skipLayout);
1454      if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
1455          MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
1456      }
1457  
1458      // update border.
1459      if (layoutProperty_->GetBorderWidthProperty()) {
1460          if (!renderContext_->HasBorderColor()) {
1461              BorderColorProperty borderColorProperty;
1462              borderColorProperty.SetColor(Color::BLACK);
1463              renderContext_->UpdateBorderColor(borderColorProperty);
1464          }
1465          if (!renderContext_->HasBorderStyle()) {
1466              BorderStyleProperty borderStyleProperty;
1467              borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
1468              renderContext_->UpdateBorderStyle(borderStyleProperty);
1469          }
1470          if (!renderContext_->HasDashGap()) {
1471              BorderWidthProperty dashGapProperty;
1472              dashGapProperty.SetBorderWidth(Dimension(-1));
1473              renderContext_->UpdateDashGap(dashGapProperty);
1474          }
1475          if (!renderContext_->HasDashWidth()) {
1476              BorderWidthProperty dashWidthProperty;
1477              dashWidthProperty.SetBorderWidth(Dimension(-1));
1478              renderContext_->UpdateDashWidth(dashWidthProperty);
1479          }
1480          if (layoutProperty_->GetLayoutConstraint().has_value()) {
1481              renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
1482                  ScaleProperty::CreateScaleProperty(),
1483                  layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
1484          } else {
1485              renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
1486                  ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
1487          }
1488      }
1489  
1490      // update background
1491      if (builderFunc_) {
1492          auto builderNode = builderFunc_();
1493          auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1494              AceType::MakeRefPtr<LinearLayoutPattern>(true));
1495          if (builderNode) {
1496              builderNode->MountToParent(columnNode);
1497          }
1498          SetBackgroundLayoutConstraint(columnNode);
1499          renderContext_->CreateBackgroundPixelMap(columnNode);
1500          builderFunc_ = nullptr;
1501          backgroundNode_ = columnNode;
1502      }
1503      UpdateFocusState();
1504  
1505      // rebuild child render node.
1506      RebuildRenderContextTree();
1507  }
1508  
SetBackgroundLayoutConstraint(const RefPtr<FrameNode> & customNode)1509  void FrameNode::SetBackgroundLayoutConstraint(const RefPtr<FrameNode>& customNode)
1510  {
1511      CHECK_NULL_VOID(customNode);
1512      LayoutConstraintF layoutConstraint;
1513      layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
1514      layoutConstraint.percentReference.SetWidth(geometryNode_->GetFrameSize().Width());
1515      layoutConstraint.percentReference.SetHeight(geometryNode_->GetFrameSize().Height());
1516      layoutConstraint.maxSize.SetWidth(geometryNode_->GetFrameSize().Width());
1517      layoutConstraint.maxSize.SetHeight(geometryNode_->GetFrameSize().Height());
1518      customNode->GetGeometryNode()->SetParentLayoutConstraint(layoutConstraint);
1519  }
1520  
AdjustGridOffset()1521  void FrameNode::AdjustGridOffset()
1522  {
1523      if (!isActive_) {
1524          return;
1525      }
1526      if (layoutProperty_->UpdateGridOffset(Claim(this))) {
1527          renderContext_->UpdateOffset(OffsetT<Dimension>());
1528          renderContext_->UpdateAnchor(OffsetT<Dimension>());
1529          renderContext_->SyncGeometryProperties(RawPtr(GetGeometryNode()));
1530      }
1531  }
1532  
ClearUserOnAreaChange()1533  void FrameNode::ClearUserOnAreaChange()
1534  {
1535      if (eventHub_) {
1536          eventHub_->ClearUserOnAreaChanged();
1537      }
1538  }
1539  
SetOnAreaChangeCallback(OnAreaChangedFunc && callback)1540  void FrameNode::SetOnAreaChangeCallback(OnAreaChangedFunc&& callback)
1541  {
1542      InitLastArea();
1543      eventHub_->SetOnAreaChanged(std::move(callback));
1544  }
1545  
TriggerOnAreaChangeCallback(uint64_t nanoTimestamp)1546  void FrameNode::TriggerOnAreaChangeCallback(uint64_t nanoTimestamp)
1547  {
1548      if (!IsActive()) {
1549          return;
1550      }
1551      if ((eventHub_->HasOnAreaChanged() || eventHub_->HasInnerOnAreaChanged()) && lastFrameRect_ &&
1552          lastParentOffsetToWindow_) {
1553          auto currFrameRect = geometryNode_->GetFrameRect();
1554          if (renderContext_ && renderContext_->GetPositionProperty()) {
1555              if (renderContext_->GetPositionProperty()->HasPosition()) {
1556                  auto renderPosition = ContextPositionConvertToPX(
1557                      renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
1558                  currFrameRect.SetOffset(
1559                      { static_cast<float>(renderPosition.first), static_cast<float>(renderPosition.second) });
1560              }
1561          }
1562          auto currParentOffsetToWindow = CalculateOffsetRelativeToWindow(nanoTimestamp) - currFrameRect.GetOffset();
1563          if (currFrameRect != *lastFrameRect_ || currParentOffsetToWindow != *lastParentOffsetToWindow_) {
1564              if (eventHub_->HasInnerOnAreaChanged()) {
1565                  eventHub_->FireInnerOnAreaChanged(
1566                      *lastFrameRect_, *lastParentOffsetToWindow_, currFrameRect, currParentOffsetToWindow);
1567              }
1568              if (eventHub_->HasOnAreaChanged()) {
1569                  eventHub_->FireOnAreaChanged(*lastFrameRect_, *lastParentOffsetToWindow_,
1570                      GetFrameRectWithSafeArea(true), GetParentGlobalOffsetWithSafeArea(true, true));
1571              }
1572              *lastFrameRect_ = currFrameRect;
1573              *lastParentOffsetToWindow_ = currParentOffsetToWindow;
1574          }
1575      }
1576      pattern_->OnAreaChangedInner();
1577  }
1578  
SetOnSizeChangeCallback(OnSizeChangedFunc && callback)1579  void FrameNode::SetOnSizeChangeCallback(OnSizeChangedFunc&& callback)
1580  {
1581      if (!lastFrameNodeRect_) {
1582          lastFrameNodeRect_ = std::make_unique<RectF>();
1583      }
1584      eventHub_->SetOnSizeChanged(std::move(callback));
1585  }
1586  
AddInnerOnSizeChangeCallback(int32_t id,OnSizeChangedFunc && callback)1587  void FrameNode::AddInnerOnSizeChangeCallback(int32_t id, OnSizeChangedFunc&& callback)
1588  {
1589      if (!lastFrameNodeRect_) {
1590          lastFrameNodeRect_ = std::make_unique<RectF>();
1591      }
1592      eventHub_->AddInnerOnSizeChanged(id, std::move(callback));
1593  }
1594  
SetJSFrameNodeOnSizeChangeCallback(OnSizeChangedFunc && callback)1595  void FrameNode::SetJSFrameNodeOnSizeChangeCallback(OnSizeChangedFunc&& callback)
1596  {
1597      if (!lastFrameNodeRect_) {
1598          lastFrameNodeRect_ = std::make_unique<RectF>();
1599      }
1600      eventHub_->SetJSFrameNodeOnSizeChangeCallback(std::move(callback));
1601  }
1602  
GetRectWithFrame()1603  RectF FrameNode::GetRectWithFrame()
1604  {
1605      auto currFrameRect = geometryNode_->GetFrameRect();
1606      if (renderContext_ && renderContext_->GetPositionProperty()) {
1607          if (renderContext_->GetPositionProperty()->HasPosition()) {
1608              auto renderPosition = ContextPositionConvertToPX(
1609                  renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
1610              currFrameRect.SetOffset(
1611                  { static_cast<float>(renderPosition.first), static_cast<float>(renderPosition.second) });
1612          }
1613      }
1614      return currFrameRect;
1615  }
1616  
GetRectWithRender()1617  RectF FrameNode::GetRectWithRender()
1618  {
1619      RectF currFrameRect;
1620      if (renderContext_) {
1621          currFrameRect = renderContext_->GetPaintRectWithoutTransform();
1622      }
1623      if (renderContext_ && renderContext_->GetPositionProperty()) {
1624          if (renderContext_->GetPositionProperty()->HasPosition()) {
1625              auto renderPosition =
1626                  ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
1627              currFrameRect.SetOffset(
1628                  { static_cast<float>(renderPosition.first), static_cast<float>(renderPosition.second) });
1629          }
1630      }
1631      return currFrameRect;
1632  }
1633  
CheckAncestorPageShow()1634  bool FrameNode::CheckAncestorPageShow()
1635  {
1636      auto pageNode = GetPageNode();
1637      if (!pageNode) {
1638          return true;
1639      }
1640      return pageNode->GetPattern<PagePattern>()->IsOnShow();
1641  }
1642  
TriggerOnSizeChangeCallback()1643  void FrameNode::TriggerOnSizeChangeCallback()
1644  {
1645      if (!IsActive() || !CheckAncestorPageShow()) {
1646          return;
1647      }
1648      if ((eventHub_->HasOnSizeChanged() || eventHub_->HasInnerOnSizeChanged()) && lastFrameNodeRect_) {
1649          auto currFrameRect = GetRectWithRender();
1650          if (currFrameRect.GetSize() != (*lastFrameNodeRect_).GetSize()) {
1651              onSizeChangeDumpInfo dumpInfo { GetCurrentTimestamp(), *lastFrameNodeRect_, currFrameRect };
1652              if (onSizeChangeDumpInfos.size() >= SIZE_CHANGE_DUMP_SIZE) {
1653                  onSizeChangeDumpInfos.erase(onSizeChangeDumpInfos.begin());
1654              }
1655              onSizeChangeDumpInfos.emplace_back(dumpInfo);
1656              if (eventHub_->HasOnSizeChanged()) {
1657                  eventHub_->FireOnSizeChanged(*lastFrameNodeRect_, currFrameRect);
1658              }
1659              if (eventHub_->HasInnerOnSizeChanged()) {
1660                  eventHub_->FireInnerOnSizeChanged(*lastFrameNodeRect_, currFrameRect);
1661              }
1662              eventHub_->FireJSFrameNodeOnSizeChanged(*lastFrameNodeRect_, currFrameRect);
1663              *lastFrameNodeRect_ = currFrameRect;
1664          }
1665      }
1666  }
1667  
IsFrameDisappear() const1668  bool FrameNode::IsFrameDisappear() const
1669  {
1670      auto context = GetContext();
1671      CHECK_NULL_RETURN(context, true);
1672      bool isFrameDisappear = !context->GetOnShow() || !IsOnMainTree() || !IsVisible();
1673      if (isFrameDisappear) {
1674          return true;
1675      }
1676      bool curFrameIsActive = isActive_;
1677      bool curIsVisible = IsVisible();
1678      auto parent = GetParent();
1679      while (parent) {
1680          auto parentFrame = AceType::DynamicCast<FrameNode>(parent);
1681          if (!parentFrame) {
1682              parent = parent->GetParent();
1683              continue;
1684          }
1685          if (!parentFrame->isActive_) {
1686              curFrameIsActive = false;
1687              break;
1688          }
1689          if (!parentFrame->IsVisible()) {
1690              curIsVisible = false;
1691              break;
1692          }
1693          parent = parent->GetParent();
1694      }
1695      return !curIsVisible || !curFrameIsActive;
1696  }
1697  
IsFrameDisappear(uint64_t timestamp)1698  bool FrameNode::IsFrameDisappear(uint64_t timestamp)
1699  {
1700      auto context = GetContext();
1701      CHECK_NULL_RETURN(context, true);
1702      auto isOnShow = context->GetOnShow();
1703      auto isOnMainTree = AllowVisibleAreaCheck();
1704      auto isSelfVisible = IsVisible();
1705      if (!isSelfVisible) {
1706          SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::SELF_INVISIBLE);
1707      }
1708      if (!isOnMainTree) {
1709          SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::IS_NOT_ON_MAINTREE);
1710      }
1711      if (!isOnShow) {
1712          SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::BACKGROUND);
1713      }
1714      bool isFrameDisappear = !isOnShow || !isOnMainTree || !isSelfVisible;
1715      if (isFrameDisappear) {
1716          cachedIsFrameDisappear_ = { timestamp, true };
1717          return true;
1718      }
1719      auto result = IsFrameAncestorDisappear(timestamp);
1720      if (result) {
1721          SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::ANCESTOR_INVISIBLE);
1722      }
1723      return result;
1724  }
1725  
IsFrameAncestorDisappear(uint64_t timestamp)1726  bool FrameNode::IsFrameAncestorDisappear(uint64_t timestamp)
1727  {
1728      bool curFrameIsActive = isActive_;
1729      bool curIsVisible = IsVisible();
1730      bool result = !curIsVisible || !curFrameIsActive;
1731      RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame();
1732      if (!parentUi) {
1733          cachedIsFrameDisappear_ = { timestamp, result };
1734          return result;
1735      }
1736  
1737      auto parentIsFrameDisappear = parentUi->cachedIsFrameDisappear_;
1738      if (parentIsFrameDisappear.first == timestamp) {
1739          result = result || parentIsFrameDisappear.second;
1740          cachedIsFrameDisappear_ = { timestamp, result };
1741          return result;
1742      }
1743      result = result || (parentUi->IsFrameAncestorDisappear(timestamp));
1744      cachedIsFrameDisappear_ = { timestamp, result };
1745      return result;
1746  }
1747  
TriggerVisibleAreaChangeCallback(uint64_t timestamp,bool forceDisappear)1748  void FrameNode::TriggerVisibleAreaChangeCallback(uint64_t timestamp, bool forceDisappear)
1749  {
1750      auto context = GetContext();
1751      CHECK_NULL_VOID(context);
1752      CHECK_NULL_VOID(eventHub_);
1753  
1754      ProcessThrottledVisibleCallback();
1755      auto hasInnerCallback = eventHub_->HasVisibleAreaCallback(false);
1756      auto hasUserCallback = eventHub_->HasVisibleAreaCallback(true);
1757      if (!hasInnerCallback && !hasUserCallback) {
1758          return;
1759      }
1760  
1761      auto& visibleAreaUserRatios = eventHub_->GetVisibleAreaRatios(true);
1762      auto& visibleAreaUserCallback = eventHub_->GetVisibleAreaCallback(true);
1763      auto& visibleAreaInnerRatios = eventHub_->GetVisibleAreaRatios(false);
1764      auto& visibleAreaInnerCallback = eventHub_->GetVisibleAreaCallback(false);
1765  
1766      if (forceDisappear || IsFrameDisappear(timestamp)) {
1767          if (!NearEqual(lastInnerVisibleRatio_, VISIBLE_RATIO_MIN)) {
1768              ProcessAllVisibleCallback(visibleAreaInnerRatios, visibleAreaInnerCallback, VISIBLE_RATIO_MIN,
1769                  lastInnerVisibleCallbackRatio_, false, true);
1770              lastInnerVisibleRatio_ = VISIBLE_RATIO_MIN;
1771          }
1772          if (!NearEqual(lastVisibleRatio_, VISIBLE_RATIO_MIN)) {
1773              ProcessAllVisibleCallback(
1774                  visibleAreaUserRatios, visibleAreaUserCallback, VISIBLE_RATIO_MIN, lastVisibleCallbackRatio_);
1775              lastVisibleRatio_ = VISIBLE_RATIO_MIN;
1776          }
1777          return;
1778      }
1779  
1780      SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::VISIBLE_AREA_CHANGE);
1781      if (hasInnerCallback) {
1782          auto visibleResult = GetCacheVisibleRect(timestamp);
1783          if (isCalculateInnerVisibleRectClip_) {
1784              ProcessVisibleAreaChangeEvent(visibleResult.innerVisibleRect, visibleResult.frameRect,
1785                  visibleAreaInnerRatios, visibleAreaInnerCallback, false);
1786          } else {
1787              ProcessVisibleAreaChangeEvent(visibleResult.visibleRect, visibleResult.frameRect,
1788                  visibleAreaInnerRatios, visibleAreaInnerCallback, false);
1789          }
1790          if (hasUserCallback) {
1791              ProcessVisibleAreaChangeEvent(visibleResult.visibleRect, visibleResult.frameRect,
1792                  visibleAreaUserRatios, visibleAreaUserCallback, true);
1793          }
1794      } else {
1795          auto visibleResult = GetCacheVisibleRect(timestamp);
1796          ProcessVisibleAreaChangeEvent(visibleResult.visibleRect, visibleResult.frameRect,
1797              visibleAreaUserRatios, visibleAreaUserCallback, true);
1798      }
1799  }
1800  
ProcessVisibleAreaChangeEvent(const RectF & visibleRect,const RectF & frameRect,const std::vector<double> & visibleAreaRatios,VisibleCallbackInfo & visibleAreaCallback,bool isUser)1801  void FrameNode::ProcessVisibleAreaChangeEvent(const RectF& visibleRect, const RectF& frameRect,
1802      const std::vector<double>& visibleAreaRatios, VisibleCallbackInfo& visibleAreaCallback, bool isUser)
1803  {
1804      double currentVisibleRatio =
1805          std::clamp(CalculateCurrentVisibleRatio(visibleRect, frameRect), VISIBLE_RATIO_MIN, VISIBLE_RATIO_MAX);
1806      if (isUser) {
1807          if (!NearEqual(currentVisibleRatio, lastVisibleRatio_)) {
1808              auto lastVisibleCallbackRatio = lastVisibleCallbackRatio_;
1809              ProcessAllVisibleCallback(
1810                  visibleAreaRatios, visibleAreaCallback, currentVisibleRatio, lastVisibleCallbackRatio);
1811              lastVisibleRatio_ = currentVisibleRatio;
1812          }
1813      } else {
1814          if (!NearEqual(currentVisibleRatio, lastInnerVisibleRatio_)) {
1815              auto lastVisibleCallbackRatio = lastInnerVisibleCallbackRatio_;
1816              ProcessAllVisibleCallback(visibleAreaRatios, visibleAreaCallback, currentVisibleRatio,
1817                  lastVisibleCallbackRatio, false, true);
1818              lastInnerVisibleRatio_ = currentVisibleRatio;
1819          }
1820      }
1821  }
1822  
CalculateCurrentVisibleRatio(const RectF & visibleRect,const RectF & renderRect)1823  double FrameNode::CalculateCurrentVisibleRatio(const RectF& visibleRect, const RectF& renderRect)
1824  {
1825      if (visibleRect.IsEmpty() || renderRect.IsEmpty()) {
1826          return 0.0;
1827      }
1828      return visibleRect.Width() * visibleRect.Height() / (renderRect.Width() * renderRect.Height());
1829  }
1830  
ProcessAllVisibleCallback(const std::vector<double> & visibleAreaUserRatios,VisibleCallbackInfo & visibleAreaUserCallback,double currentVisibleRatio,double lastVisibleRatio,bool isThrottled,bool isInner)1831  void FrameNode::ProcessAllVisibleCallback(const std::vector<double>& visibleAreaUserRatios,
1832      VisibleCallbackInfo& visibleAreaUserCallback, double currentVisibleRatio, double lastVisibleRatio,
1833      bool isThrottled, bool isInner)
1834  {
1835      bool isHandled = false;
1836      bool isVisible = false;
1837      double* lastVisibleCallbackRatio = isThrottled ? &lastThrottledVisibleCbRatio_ :
1838          (isInner ? &lastInnerVisibleCallbackRatio_ : &lastVisibleCallbackRatio_);
1839  
1840      for (const auto& callbackRatio : visibleAreaUserRatios) {
1841          if (GreatNotEqual(currentVisibleRatio, callbackRatio) && LessOrEqual(lastVisibleRatio, callbackRatio)) {
1842              *lastVisibleCallbackRatio = currentVisibleRatio;
1843              isVisible = true;
1844              isHandled = true;
1845          } else if (LessNotEqual(currentVisibleRatio, callbackRatio) && GreatOrEqual(lastVisibleRatio, callbackRatio)) {
1846              *lastVisibleCallbackRatio = currentVisibleRatio;
1847              isVisible = false;
1848              isHandled = true;
1849          } else if (NearEqual(callbackRatio, VISIBLE_RATIO_MIN) && NearEqual(currentVisibleRatio, callbackRatio)) {
1850              *lastVisibleCallbackRatio = VISIBLE_RATIO_MIN;
1851              currentVisibleRatio = VISIBLE_RATIO_MIN;
1852              isVisible = false;
1853              isHandled = true;
1854          } else if (NearEqual(callbackRatio, VISIBLE_RATIO_MAX) && NearEqual(currentVisibleRatio, callbackRatio)) {
1855              *lastVisibleCallbackRatio = VISIBLE_RATIO_MAX;
1856              currentVisibleRatio = VISIBLE_RATIO_MAX;
1857              isVisible = true;
1858              isHandled = true;
1859          }
1860      }
1861  
1862      auto callback = visibleAreaUserCallback.callback;
1863      if (isHandled && callback) {
1864          if (GetTag() == V2::WEB_ETS_TAG) {
1865              TAG_LOGI(AceLogTag::ACE_UIEVENT, "exp=%{public}d ratio=%{public}s %{public}d-%{public}s reason=%{public}d",
1866                  isVisible, std::to_string(currentVisibleRatio).c_str(), GetId(),
1867                  std::to_string(GetAccessibilityId()).c_str(), static_cast<int32_t>(visibleAreaChangeTriggerReason_));
1868          }
1869          callback(isVisible, currentVisibleRatio);
1870      }
1871  }
1872  
ThrottledVisibleTask()1873  void FrameNode::ThrottledVisibleTask()
1874  {
1875      CHECK_NULL_VOID(eventHub_);
1876      auto& userRatios = eventHub_->GetThrottledVisibleAreaRatios();
1877      auto& userCallback = eventHub_->GetThrottledVisibleAreaCallback();
1878      CHECK_NULL_VOID(userCallback.callback);
1879      if (!throttledCallbackOnTheWay_) {
1880          return;
1881      }
1882  
1883      auto pipeline = GetContext();
1884      CHECK_NULL_VOID(pipeline);
1885      auto visibleAreaRealTime = pipeline->GetVisibleAreaRealTime();
1886      auto visibleResult = GetCacheVisibleRect(pipeline->GetVsyncTime());
1887      RectF frameRect = visibleResult.frameRect;
1888      RectF visibleRect = visibleResult.visibleRect;
1889      double ratio = IsFrameDisappear() ? VISIBLE_RATIO_MIN
1890                                        : std::clamp(CalculateCurrentVisibleRatio(visibleRect, frameRect),
1891                                            VISIBLE_RATIO_MIN, VISIBLE_RATIO_MAX);
1892      if (visibleAreaRealTime) {
1893          if (NearEqual(ratio, lastThrottledVisibleRatio_)) {
1894              throttledCallbackOnTheWay_ = false;
1895              return;
1896          }
1897          ProcessAllVisibleCallback(userRatios, userCallback, ratio, lastThrottledVisibleCbRatio_, true);
1898          lastThrottledVisibleRatio_ = ratio;
1899          throttledCallbackOnTheWay_ = false;
1900          lastThrottledTriggerTime_ = GetCurrentTimestamp();
1901      } else {
1902          if (!NearEqual(ratio, lastThrottledVisibleRatio_)) {
1903              ProcessAllVisibleCallback(userRatios, userCallback, ratio, lastThrottledVisibleCbRatio_, true);
1904              lastThrottledVisibleRatio_ = ratio;
1905          }
1906          throttledCallbackOnTheWay_ = false;
1907          lastThrottledTriggerTime_ = GetCurrentTimestamp();
1908      }
1909  }
1910  
ProcessThrottledVisibleCallback()1911  void FrameNode::ProcessThrottledVisibleCallback()
1912  {
1913      CHECK_NULL_VOID(eventHub_);
1914      auto& visibleAreaUserCallback = eventHub_->GetThrottledVisibleAreaCallback();
1915      CHECK_NULL_VOID(visibleAreaUserCallback.callback);
1916  
1917      auto task = [weak = WeakClaim(this)]() {
1918          auto node = weak.Upgrade();
1919          CHECK_NULL_VOID(node);
1920          node->ThrottledVisibleTask();
1921      };
1922  
1923      auto pipeline = GetContextRefPtr();
1924      CHECK_NULL_VOID(pipeline);
1925      auto executor = pipeline->GetTaskExecutor();
1926      CHECK_NULL_VOID(executor);
1927  
1928      if (throttledCallbackOnTheWay_) {
1929          return;
1930      }
1931  
1932      throttledCallbackOnTheWay_ = true;
1933      int64_t interval = GetCurrentTimestamp() - lastThrottledTriggerTime_;
1934      if (interval < visibleAreaUserCallback.period) {
1935          executor->PostDelayedTask(std::move(task), TaskExecutor::TaskType::UI, visibleAreaUserCallback.period,
1936              "ThrottledVisibleChangeCallback", PriorityType::IDLE);
1937      } else {
1938          executor->PostTask(
1939              std::move(task), TaskExecutor::TaskType::UI, "ThrottledVisibleChangeCallback", PriorityType::IDLE);
1940      }
1941  }
1942  
SetActive(bool active,bool needRebuildRenderContext)1943  void FrameNode::SetActive(bool active, bool needRebuildRenderContext)
1944  {
1945      bool activeChanged = false;
1946      if (active && !isActive_) {
1947          pattern_->OnActive();
1948          isActive_ = true;
1949          activeChanged = true;
1950      }
1951      if (!active && isActive_) {
1952          pattern_->OnInActive();
1953          isActive_ = false;
1954          activeChanged = true;
1955      }
1956      CHECK_NULL_VOID(activeChanged);
1957      auto parent = GetAncestorNodeOfFrame();
1958      if (parent) {
1959          parent->MarkNeedSyncRenderTree();
1960          if (needRebuildRenderContext) {
1961              auto pipeline = GetContext();
1962              CHECK_NULL_VOID(pipeline);
1963              auto task = [weak = AceType::WeakClaim(AceType::RawPtr(parent))]() {
1964                  auto parent = weak.Upgrade();
1965                  CHECK_NULL_VOID(parent);
1966                  parent->RebuildRenderContextTree();
1967              };
1968              pipeline->AddAfterLayoutTask(task);
1969          }
1970      }
1971      if (isActive_ && SystemProperties::GetDeveloperModeOn()) {
1972          PaintDebugBoundary(SystemProperties::GetDebugBoundaryEnabled());
1973      }
1974  }
1975  
SetGeometryNode(const RefPtr<GeometryNode> & node)1976  void FrameNode::SetGeometryNode(const RefPtr<GeometryNode>& node)
1977  {
1978      geometryNode_ = node;
1979  }
1980  
CreateLayoutTask(bool forceUseMainThread)1981  void FrameNode::CreateLayoutTask(bool forceUseMainThread)
1982  {
1983      if (!isLayoutDirtyMarked_) {
1984          return;
1985      }
1986      SetRootMeasureNode(true);
1987      UpdateLayoutPropertyFlag();
1988      SetSkipSyncGeometryNode(false);
1989      if (layoutProperty_->GetLayoutRect()) {
1990          SetActive(true, true);
1991          Measure(std::nullopt);
1992          Layout();
1993      } else {
1994          {
1995              auto layoutConstraint = GetLayoutConstraint();
1996              ACE_SCOPED_TRACE("CreateTaskMeasure[%s][self:%d][parent:%d][layoutConstraint:%s]", GetTag().c_str(),
1997                  GetId(), GetAncestorNodeOfFrame() ? GetAncestorNodeOfFrame()->GetId() : 0,
1998                  layoutConstraint.ToString().c_str());
1999              Measure(layoutConstraint);
2000          }
2001          {
2002              ACE_SCOPED_TRACE("CreateTaskLayout[%s][self:%d][parent:%d]", GetTag().c_str(), GetId(),
2003                  GetAncestorNodeOfFrame() ? GetAncestorNodeOfFrame()->GetId() : 0);
2004              Layout();
2005          }
2006      }
2007      SetRootMeasureNode(false);
2008  }
2009  
CreateRenderTask(bool forceUseMainThread)2010  std::optional<UITask> FrameNode::CreateRenderTask(bool forceUseMainThread)
2011  {
2012      if (!isRenderDirtyMarked_) {
2013          return std::nullopt;
2014      }
2015      auto wrapper = CreatePaintWrapper();
2016      CHECK_NULL_RETURN(wrapper, std::nullopt);
2017      auto task = [weak = WeakClaim(this), wrapper, paintProperty = paintProperty_]() {
2018          auto self = weak.Upgrade();
2019          ACE_SCOPED_TRACE("FrameNode[%s][id:%d]::RenderTask", self->GetTag().c_str(), self->GetId());
2020          ArkUIPerfMonitor::GetInstance().RecordRenderNode();
2021          wrapper->FlushRender();
2022          paintProperty->CleanDirty();
2023  
2024          if (self->GetInspectorId()) {
2025              auto pipeline = PipelineContext::GetCurrentContext();
2026              CHECK_NULL_VOID(pipeline);
2027              pipeline->SetNeedRenderNode(weak);
2028          }
2029      };
2030      if (forceUseMainThread || wrapper->CheckShouldRunOnMain()) {
2031          return UITask(std::move(task), MAIN_TASK);
2032      }
2033      return UITask(std::move(task), wrapper->CanRunOnWhichThread());
2034  }
2035  
GetLayoutConstraint() const2036  LayoutConstraintF FrameNode::GetLayoutConstraint() const
2037  {
2038      if (geometryNode_->GetParentLayoutConstraint().has_value()) {
2039          return geometryNode_->GetParentLayoutConstraint().value();
2040      }
2041      LayoutConstraintF layoutConstraint;
2042      layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
2043      auto rootWidth = PipelineContext::GetCurrentRootWidth();
2044      auto rootHeight = PipelineContext::GetCurrentRootHeight();
2045      layoutConstraint.percentReference.SetWidth(rootWidth);
2046      layoutConstraint.percentReference.SetHeight(rootHeight);
2047      layoutConstraint.maxSize.SetWidth(rootWidth);
2048      layoutConstraint.maxSize.SetHeight(rootHeight);
2049      return layoutConstraint;
2050  }
2051  
GetParentGlobalOffset() const2052  OffsetF FrameNode::GetParentGlobalOffset() const
2053  {
2054      auto parent = GetAncestorNodeOfFrame();
2055      if (!parent) {
2056          return { 0.0f, 0.0f };
2057      }
2058      return parent->geometryNode_->GetParentGlobalOffset();
2059  }
2060  
UpdateLayoutPropertyFlag()2061  void FrameNode::UpdateLayoutPropertyFlag()
2062  {
2063      auto selfFlag = layoutProperty_->GetPropertyChangeFlag();
2064      if (!CheckUpdateByChildRequest(selfFlag)) {
2065          return;
2066      }
2067      if (CheckForceParentMeasureFlag(selfFlag)) {
2068          return;
2069      }
2070      auto flag = PROPERTY_UPDATE_NORMAL;
2071      const auto& children = GetChildren();
2072      for (const auto& child : children) {
2073          child->UpdateLayoutPropertyFlag();
2074          child->AdjustParentLayoutFlag(flag);
2075          if (CheckForceParentMeasureFlag(selfFlag)) {
2076              break;
2077          }
2078      }
2079      if (CheckForceParentMeasureFlag(flag)) {
2080          layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
2081      }
2082  }
2083  
ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeFlag)2084  void FrameNode::ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeFlag)
2085  {
2086      layoutProperty_->UpdatePropertyChangeFlag(propertyChangeFlag);
2087  }
2088  
AdjustParentLayoutFlag(PropertyChangeFlag & flag)2089  void FrameNode::AdjustParentLayoutFlag(PropertyChangeFlag& flag)
2090  {
2091      flag = flag | layoutProperty_->GetPropertyChangeFlag();
2092  }
2093  
CreateLayoutWrapper(bool forceMeasure,bool forceLayout)2094  RefPtr<LayoutWrapperNode> FrameNode::CreateLayoutWrapper(bool forceMeasure, bool forceLayout)
2095  {
2096      return UpdateLayoutWrapper(nullptr, forceMeasure, forceLayout);
2097  }
2098  
UpdateLayoutWrapper(RefPtr<LayoutWrapperNode> layoutWrapper,bool forceMeasure,bool forceLayout)2099  RefPtr<LayoutWrapperNode> FrameNode::UpdateLayoutWrapper(
2100      RefPtr<LayoutWrapperNode> layoutWrapper, bool forceMeasure, bool forceLayout)
2101  {
2102      CHECK_NULL_RETURN(layoutProperty_, nullptr);
2103      CHECK_NULL_RETURN(pattern_, nullptr);
2104      if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
2105          if (!layoutWrapper) {
2106              layoutWrapper =
2107                  MakeRefPtr<LayoutWrapperNode>(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
2108          } else {
2109              layoutWrapper->Update(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
2110          }
2111          layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
2112          isLayoutDirtyMarked_ = false;
2113          return layoutWrapper;
2114      }
2115  
2116      pattern_->BeforeCreateLayoutWrapper();
2117      if (forceMeasure) {
2118          layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
2119      }
2120      if (forceLayout) {
2121          layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
2122      }
2123      auto flag = layoutProperty_->GetPropertyChangeFlag();
2124      // It is necessary to copy the layoutProperty property to prevent the layoutProperty property from being
2125      // modified during the layout process, resulting in the problem of judging whether the front-end setting value
2126      // changes the next time js is executed.
2127      if (!layoutWrapper) {
2128          layoutWrapper =
2129              MakeRefPtr<LayoutWrapperNode>(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
2130      } else {
2131          layoutWrapper->Update(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
2132      }
2133      do {
2134          if (CheckNeedMeasure(flag) || forceMeasure) {
2135              layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm()));
2136              bool forceChildMeasure = CheckMeasureFlag(flag) || CheckMeasureSelfAndChildFlag(flag) || forceMeasure;
2137              UpdateChildrenLayoutWrapper(layoutWrapper, forceChildMeasure, false);
2138              break;
2139          }
2140          if (CheckNeedLayout(flag) || forceLayout) {
2141              layoutWrapper->SetLayoutAlgorithm(
2142                  MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm(), true, false));
2143              UpdateChildrenLayoutWrapper(layoutWrapper, false, false);
2144              break;
2145          }
2146          layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
2147      } while (false);
2148      // check position flag.
2149      layoutWrapper->SetOutOfLayout(renderContext_->HasPosition());
2150      layoutWrapper->SetActive(isActive_);
2151      layoutWrapper->SetIsOverlayNode(layoutProperty_->IsOverlayNode());
2152      isLayoutDirtyMarked_ = false;
2153      return layoutWrapper;
2154  }
2155  
UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapperNode> & self,bool forceMeasure,bool forceLayout)2156  void FrameNode::UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapperNode>& self, bool forceMeasure, bool forceLayout)
2157  {
2158      const auto& children = GetChildren();
2159      for (const auto& child : children) {
2160          child->AdjustLayoutWrapperTree(self, forceMeasure, forceLayout);
2161      }
2162  }
2163  
AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode> & parent,bool forceMeasure,bool forceLayout)2164  void FrameNode::AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode>& parent, bool forceMeasure, bool forceLayout)
2165  {
2166      ACE_DCHECK(parent);
2167      CHECK_NULL_VOID(layoutProperty_);
2168      const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
2169      if (geometryTransition != nullptr && geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
2170          return;
2171      }
2172      auto layoutWrapper = CreateLayoutWrapper(forceMeasure, forceLayout);
2173      parent->AppendChild(layoutWrapper, layoutProperty_->IsOverlayNode());
2174  }
2175  
GetContentModifier()2176  RefPtr<ContentModifier> FrameNode::GetContentModifier()
2177  {
2178      CHECK_NULL_RETURN(pattern_, nullptr);
2179      auto wrapper = CreatePaintWrapper();
2180      CHECK_NULL_RETURN(wrapper, nullptr);
2181      auto paintMethod = pattern_->CreateNodePaintMethod();
2182      if (!paintMethod || extensionHandler_ || renderContext_->GetAccessibilityFocus().value_or(false)) {
2183          paintMethod = pattern_->CreateDefaultNodePaintMethod();
2184      }
2185      CHECK_NULL_RETURN(paintMethod, nullptr);
2186      auto contentModifier = DynamicCast<ContentModifier>(paintMethod->GetContentModifier(AceType::RawPtr(wrapper)));
2187      return contentModifier;
2188  }
2189  
CreatePaintWrapper()2190  RefPtr<PaintWrapper> FrameNode::CreatePaintWrapper()
2191  {
2192      pattern_->BeforeCreatePaintWrapper();
2193      isRenderDirtyMarked_ = false;
2194      auto paintMethod = pattern_->CreateNodePaintMethod();
2195      if (paintMethod || extensionHandler_ || renderContext_->GetAccessibilityFocus().value_or(false)) {
2196          // It is necessary to copy the layoutProperty property to prevent the paintProperty_ property from being
2197          // modified during the paint process, resulting in the problem of judging whether the front-end setting value
2198          // changes the next time js is executed.
2199          if (!paintMethod) {
2200              paintMethod = pattern_->CreateDefaultNodePaintMethod();
2201          }
2202  
2203          auto paintWrapper = MakeRefPtr<PaintWrapper>(
2204              renderContext_, geometryNode_->Clone(), paintProperty_->Clone(), extensionHandler_);
2205          paintWrapper->SetNodePaintMethod(paintMethod);
2206          return paintWrapper;
2207      }
2208      return nullptr;
2209  }
2210  
PostIdleTask(std::function<void (int64_t deadline,bool canUseLongPredictTask)> && task)2211  void FrameNode::PostIdleTask(std::function<void(int64_t deadline, bool canUseLongPredictTask)>&& task)
2212  {
2213      auto context = GetContext();
2214      CHECK_NULL_VOID(context);
2215      context->AddPredictTask(std::move(task));
2216  }
2217  
UpdateLayoutConstraint(const MeasureProperty & calcLayoutConstraint)2218  void FrameNode::UpdateLayoutConstraint(const MeasureProperty& calcLayoutConstraint)
2219  {
2220      layoutProperty_->UpdateCalcLayoutProperty(calcLayoutConstraint);
2221  }
2222  
RebuildRenderContextTree()2223  void FrameNode::RebuildRenderContextTree()
2224  {
2225      if (!needSyncRenderTree_) {
2226          return;
2227      }
2228      auto pipeline = GetContextRefPtr();
2229      if (pipeline && !pipeline->CheckThreadSafe()) {
2230          LOGW("RebuildRenderContextTree doesn't run on UI thread!");
2231      }
2232      frameChildren_.clear();
2233      std::list<RefPtr<FrameNode>> children;
2234      // generate full children list, including disappear children.
2235      GenerateOneDepthVisibleFrameWithTransition(children);
2236      if (overlayNode_) {
2237          auto property = overlayNode_->GetLayoutProperty();
2238          if (property && property->GetVisibilityValue(VisibleType::VISIBLE) == VisibleType::VISIBLE) {
2239              children.push_back(overlayNode_);
2240          }
2241      }
2242      for (const auto& child : children) {
2243          frameChildren_.emplace(child);
2244      }
2245      renderContext_->RebuildFrame(this, children);
2246      pattern_->OnRebuildFrame();
2247      needSyncRenderTree_ = false;
2248  }
2249  
MarkModifyDone()2250  void FrameNode::MarkModifyDone()
2251  {
2252      pattern_->OnModifyDone();
2253      auto pipeline = PipelineContext::GetCurrentContextSafely();
2254      if (pipeline) {
2255          auto privacyManager = pipeline->GetPrivacySensitiveManager();
2256          if (privacyManager) {
2257              if (IsPrivacySensitive()) {
2258                  LOGI("store sensitive node, %{public}d", GetId());
2259                  privacyManager->StoreNode(AceType::WeakClaim(this));
2260              } else {
2261                  privacyManager->RemoveNode(AceType::WeakClaim(this));
2262              }
2263          }
2264      }
2265      if (!isRestoreInfoUsed_) {
2266          isRestoreInfoUsed_ = true;
2267          int32_t restoreId = GetRestoreId();
2268          if (pipeline && restoreId >= 0) {
2269              // store distribute node
2270              pipeline->StoreNode(restoreId, AceType::WeakClaim(this));
2271              // restore distribute node info
2272              std::string restoreInfo;
2273              if (pipeline->GetRestoreInfo(restoreId, restoreInfo)) {
2274                  pattern_->OnRestoreInfo(restoreInfo);
2275              }
2276          }
2277      }
2278      eventHub_->MarkModifyDone();
2279      renderContext_->OnModifyDone();
2280  #if (defined(__aarch64__) || defined(__x86_64__))
2281      if (Recorder::IsCacheAvaliable()) {
2282          auto pipeline = PipelineContext::GetCurrentContext();
2283          CHECK_NULL_VOID(pipeline);
2284          pipeline->AddAfterRenderTask([weak = WeakPtr(pattern_)]() {
2285              auto pattern = weak.Upgrade();
2286              CHECK_NULL_VOID(pattern);
2287              pattern->OnAfterModifyDone();
2288          });
2289      }
2290  #endif
2291  }
2292  
OnMountToParentDone()2293  void FrameNode::OnMountToParentDone()
2294  {
2295      pattern_->OnMountToParentDone();
2296  }
2297  
AfterMountToParent()2298  void FrameNode::AfterMountToParent()
2299  {
2300      if (pattern_) {
2301          pattern_->AfterMountToParent();
2302      }
2303  }
2304  
FlushUpdateAndMarkDirty()2305  void FrameNode::FlushUpdateAndMarkDirty()
2306  {
2307      MarkDirtyNode();
2308  }
2309  
MarkDirtyNode(PropertyChangeFlag extraFlag)2310  void FrameNode::MarkDirtyNode(PropertyChangeFlag extraFlag)
2311  {
2312      if (IsFreeze()) {
2313          // store the flag.
2314          layoutProperty_->UpdatePropertyChangeFlag(extraFlag);
2315          paintProperty_->UpdatePropertyChangeFlag(extraFlag);
2316          return;
2317      }
2318      if (CheckNeedMakePropertyDiff(extraFlag)) {
2319          if (isPropertyDiffMarked_) {
2320              return;
2321          }
2322          auto context = GetContextWithCheck();
2323          CHECK_NULL_VOID(context);
2324          context->AddDirtyPropertyNode(Claim(this));
2325          isPropertyDiffMarked_ = true;
2326          return;
2327      }
2328      MarkDirtyNode(IsMeasureBoundary(), IsRenderBoundary(), extraFlag);
2329  }
2330  
ProcessFreezeNode()2331  void FrameNode::ProcessFreezeNode()
2332  {
2333      MarkDirtyNode();
2334  }
2335  
OnFreezeStateChange()2336  void FrameNode::OnFreezeStateChange()
2337  {
2338      if (IsFreeze()) {
2339          return;
2340      }
2341      // unlock freeze, mark dirty to process freeze node.
2342      auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
2343      auto paintFlag = paintProperty_->GetPropertyChangeFlag();
2344      if (CheckNoChanged(layoutFlag | paintFlag)) {
2345          return;
2346      }
2347      auto pipeline = GetContext();
2348      CHECK_NULL_VOID(pipeline);
2349      pipeline->AddDirtyFreezeNode(this);
2350  }
2351  
GetAncestorNodeOfFrame(bool checkBoundary) const2352  RefPtr<FrameNode> FrameNode::GetAncestorNodeOfFrame(bool checkBoundary) const
2353  {
2354      if (checkBoundary && IsWindowBoundary()) {
2355          return nullptr;
2356      }
2357      auto parent = GetParent();
2358      while (parent) {
2359          auto parentFrame = DynamicCast<FrameNode>(parent);
2360          if (parentFrame) {
2361              return parentFrame;
2362          }
2363          parent = parent->GetParent();
2364      }
2365      return nullptr;
2366  }
2367  
GetPageNode()2368  RefPtr<FrameNode> FrameNode::GetPageNode()
2369  {
2370      if (GetTag() == "page") {
2371          return Claim(this);
2372      }
2373      auto parent = GetParent();
2374      while (parent && parent->GetTag() != "page") {
2375          parent = parent->GetParent();
2376      }
2377      return AceType::DynamicCast<FrameNode>(parent);
2378  }
2379  
GetFirstAutoFillContainerNode()2380  RefPtr<FrameNode> FrameNode::GetFirstAutoFillContainerNode()
2381  {
2382      if (IsAutoFillContainerNode()) {
2383          return Claim(this);
2384      }
2385      auto parent = GetParent();
2386      while (parent && !parent->IsAutoFillContainerNode()) {
2387          parent = parent->GetParent();
2388      }
2389      return AceType::DynamicCast<FrameNode>(parent);
2390  }
2391  
NotifyFillRequestSuccess(RefPtr<ViewDataWrap> viewDataWrap,RefPtr<PageNodeInfoWrap> nodeWrap,AceAutoFillType autoFillType)2392  void FrameNode::NotifyFillRequestSuccess(
2393      RefPtr<ViewDataWrap> viewDataWrap, RefPtr<PageNodeInfoWrap> nodeWrap, AceAutoFillType autoFillType)
2394  {
2395      if (pattern_) {
2396          pattern_->NotifyFillRequestSuccess(viewDataWrap, nodeWrap, autoFillType);
2397      }
2398  }
2399  
NotifyFillRequestFailed(int32_t errCode,const std::string & fillContent,bool isPopup)2400  void FrameNode::NotifyFillRequestFailed(int32_t errCode, const std::string& fillContent, bool isPopup)
2401  {
2402      if (pattern_) {
2403          pattern_->NotifyFillRequestFailed(errCode, fillContent, isPopup);
2404      }
2405  }
2406  
MarkNeedRenderOnly()2407  void FrameNode::MarkNeedRenderOnly()
2408  {
2409      MarkNeedRender(IsRenderBoundary());
2410  }
2411  
MarkNeedRender(bool isRenderBoundary)2412  void FrameNode::MarkNeedRender(bool isRenderBoundary)
2413  {
2414      auto context = GetContext();
2415      CHECK_NULL_VOID(context);
2416      // If it has dirtyLayoutBox, need to mark dirty after layout done.
2417      paintProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_RENDER);
2418      if (isRenderDirtyMarked_ || isLayoutDirtyMarked_) {
2419          return;
2420      }
2421      isRenderDirtyMarked_ = true;
2422      if (isRenderBoundary) {
2423          context->AddDirtyRenderNode(Claim(this));
2424          return;
2425      }
2426      auto parent = GetAncestorNodeOfFrame();
2427      if (parent) {
2428          parent->MarkDirtyNode(PROPERTY_UPDATE_RENDER_BY_CHILD_REQUEST);
2429      }
2430  }
2431  
RequestParentDirty()2432  bool FrameNode::RequestParentDirty()
2433  {
2434      auto parent = GetAncestorNodeOfFrame();
2435      CHECK_NULL_RETURN(parent, false);
2436      parent->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
2437      return true;
2438  }
2439  
MarkDirtyNode(bool isMeasureBoundary,bool isRenderBoundary,PropertyChangeFlag extraFlag)2440  void FrameNode::MarkDirtyNode(bool isMeasureBoundary, bool isRenderBoundary, PropertyChangeFlag extraFlag)
2441  {
2442      layoutProperty_->UpdatePropertyChangeFlag(extraFlag);
2443      paintProperty_->UpdatePropertyChangeFlag(extraFlag);
2444      auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
2445      auto paintFlag = paintProperty_->GetPropertyChangeFlag();
2446      if (CheckNoChanged(layoutFlag | paintFlag)) {
2447          return;
2448      }
2449      auto context = GetContext();
2450      CHECK_NULL_VOID(context);
2451  
2452      if (CheckNeedRequestMeasureAndLayout(layoutFlag)) {
2453          if ((!isMeasureBoundary && IsNeedRequestParentMeasure())) {
2454              if (RequestParentDirty()) {
2455                  return;
2456              }
2457          }
2458          if (isLayoutDirtyMarked_) {
2459              return;
2460          }
2461          isLayoutDirtyMarked_ = true;
2462          context->AddDirtyLayoutNode(Claim(this));
2463          return;
2464      }
2465      layoutProperty_->CleanDirty();
2466      MarkNeedRender(isRenderBoundary);
2467  }
2468  
IsNeedRequestParentMeasure() const2469  bool FrameNode::IsNeedRequestParentMeasure() const
2470  {
2471      auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
2472      if (layoutFlag == PROPERTY_UPDATE_BY_CHILD_REQUEST) {
2473          const auto& calcLayoutConstraint = layoutProperty_->GetCalcLayoutConstraint();
2474          if (calcLayoutConstraint && calcLayoutConstraint->selfIdealSize &&
2475              calcLayoutConstraint->selfIdealSize->IsValid()) {
2476              return false;
2477          }
2478      }
2479      return CheckNeedRequestParentMeasure(layoutFlag);
2480  }
2481  
OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & visibleList)2482  void FrameNode::OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& visibleList)
2483  {
2484      if (isLayoutNode_) {
2485          UINode::GenerateOneDepthVisibleFrame(visibleList);
2486          if (overlayNode_) {
2487              visibleList.emplace_back(overlayNode_);
2488          }
2489          return;
2490      }
2491      if (isActive_ && IsVisible()) {
2492          visibleList.emplace_back(Claim(this));
2493      }
2494  }
2495  
OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>> & allList)2496  void FrameNode::OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>>& allList)
2497  {
2498      allList.emplace_back(Claim(this));
2499  }
2500  
OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>> & visibleList)2501  void FrameNode::OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>>& visibleList)
2502  {
2503      if (isLayoutNode_) {
2504          UINode::GenerateOneDepthVisibleFrameWithTransition(visibleList);
2505          if (overlayNode_) {
2506              visibleList.emplace_back(overlayNode_);
2507          }
2508          return;
2509      }
2510  
2511      auto context = GetRenderContext();
2512      CHECK_NULL_VOID(context);
2513      // skip if 1.not active or 2.not visible and has no transition out animation.
2514      if (!isActive_ || (!IsVisible() && !context->HasTransitionOutAnimation())) {
2515          return;
2516      }
2517      visibleList.emplace_back(Claim(this));
2518  }
2519  
OnGenerateOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>> & visibleList,OffsetF & offset)2520  void FrameNode::OnGenerateOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>>& visibleList, OffsetF& offset)
2521  {
2522      if (isLayoutNode_) {
2523          isFind_ = true;
2524          offset += GetGeometryNode()->GetFrameOffset();
2525          UINode::GenerateOneDepthVisibleFrameWithOffset(visibleList, offset);
2526          if (overlayNode_) {
2527              visibleList.emplace_back(overlayNode_);
2528          }
2529          return;
2530      }
2531  
2532      auto context = GetRenderContext();
2533      CHECK_NULL_VOID(context);
2534      // skip if 1.not active or 2.not visible and has no transition out animation.
2535      if (!isActive_ || (!IsVisible() && !context->HasTransitionOutAnimation())) {
2536          return;
2537      }
2538      visibleList.emplace_back(Claim(this));
2539  }
2540  
IsMeasureBoundary()2541  bool FrameNode::IsMeasureBoundary()
2542  {
2543      return isMeasureBoundary_ || pattern_->IsMeasureBoundary();
2544  }
2545  
IsRenderBoundary()2546  bool FrameNode::IsRenderBoundary()
2547  {
2548      return pattern_->IsRenderBoundary();
2549  }
2550  
GetPattern() const2551  const RefPtr<Pattern>& FrameNode::GetPattern() const
2552  {
2553      return pattern_;
2554  }
2555  
IsAtomicNode() const2556  bool FrameNode::IsAtomicNode() const
2557  {
2558      return pattern_->IsAtomicNode();
2559  }
2560  
GetHitTestMode() const2561  HitTestMode FrameNode::GetHitTestMode() const
2562  {
2563      auto gestureHub = eventHub_->GetGestureEventHub();
2564      return gestureHub ? gestureHub->GetHitTestMode() : HitTestMode::HTMDEFAULT;
2565  }
2566  
SetHitTestMode(HitTestMode mode)2567  void FrameNode::SetHitTestMode(HitTestMode mode)
2568  {
2569      auto gestureHub = eventHub_->GetOrCreateGestureEventHub();
2570      CHECK_NULL_VOID(gestureHub);
2571      gestureHub->SetHitTestMode(mode);
2572  }
2573  
GetTouchable() const2574  bool FrameNode::GetTouchable() const
2575  {
2576      auto gestureHub = eventHub_->GetGestureEventHub();
2577      return gestureHub ? gestureHub->GetTouchable() : true;
2578  }
2579  
GetMonopolizeEvents() const2580  bool FrameNode::GetMonopolizeEvents() const
2581  {
2582      auto gestureHub = eventHub_->GetGestureEventHub();
2583      return gestureHub ? gestureHub->GetMonopolizeEvents() : false;
2584  }
2585  
GetPaintRectWithTransform() const2586  RectF FrameNode::GetPaintRectWithTransform() const
2587  {
2588      return renderContext_->GetPaintRectWithTransform();
2589  }
2590  
GetTransformScale() const2591  VectorF FrameNode::GetTransformScale() const
2592  {
2593      return renderContext_->GetTransformScaleValue({ 1.0f, 1.0f });
2594  }
2595  
IsPaintRectWithTransformValid()2596  bool FrameNode::IsPaintRectWithTransformValid()
2597  {
2598      auto paintRectWithTransform = renderContext_->GetPaintRectWithTransform();
2599      if (NearZero(paintRectWithTransform.Width()) || NearZero(paintRectWithTransform.Height())) {
2600          return true;
2601      }
2602      return false;
2603  }
2604  
IsOutOfTouchTestRegion(const PointF & parentRevertPoint,const TouchEvent & touchEvent)2605  bool FrameNode::IsOutOfTouchTestRegion(const PointF& parentRevertPoint, const TouchEvent& touchEvent)
2606  {
2607      bool isInChildRegion = false;
2608      auto paintRect = renderContext_->GetPaintRectWithoutTransform();
2609      if (pattern_->IsResponseRegionExpandingNeededForStylus(touchEvent)) {
2610          paintRect = pattern_->ExpandDefaultResponseRegion(paintRect);
2611      }
2612      auto responseRegionList = GetResponseRegionList(paintRect, static_cast<int32_t>(touchEvent.sourceType));
2613  
2614      auto revertPoint = parentRevertPoint;
2615      MapPointTo(revertPoint, GetOrRefreshRevertMatrixFromCache());
2616      auto subRevertPoint = revertPoint - paintRect.GetOffset();
2617      auto clip = renderContext_->GetClipEdge().value_or(false);
2618      if (!InResponseRegionList(revertPoint, responseRegionList) || !GetTouchable() ||
2619          IsPaintRectWithTransformValid()) {
2620          if (clip) {
2621              return true;
2622          }
2623          for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
2624              const auto& child = iter->Upgrade();
2625              if (child && !child->IsOutOfTouchTestRegion(subRevertPoint, touchEvent)) {
2626                  isInChildRegion = true;
2627                  break;
2628              }
2629          }
2630          if (!isInChildRegion) {
2631              return true;
2632          }
2633      }
2634      return false;
2635  }
2636  
AddJudgeToTargetComponent(RefPtr<TargetComponent> & targetComponent)2637  void FrameNode::AddJudgeToTargetComponent(RefPtr<TargetComponent>& targetComponent)
2638  {
2639      auto gestureHub = eventHub_->GetGestureEventHub();
2640      if (gestureHub) {
2641          auto callback = gestureHub->GetOnGestureJudgeBeginCallback();
2642          targetComponent->SetOnGestureJudgeBegin(std::move(callback));
2643          auto callbackNative = gestureHub->GetOnGestureJudgeNativeBeginCallback();
2644          if (callbackNative) {
2645              targetComponent->SetOnGestureJudgeNativeBegin(std::move(callbackNative));
2646          }
2647  
2648          if (!targetComponent->IsInnerNodeGestureRecognizerJudgeSet()) {
2649              auto gestureRecognizerJudgeCallback = gestureHub->GetOnGestureRecognizerJudgeBegin();
2650              targetComponent->SetOnGestureRecognizerJudgeBegin(std::move(gestureRecognizerJudgeCallback));
2651          }
2652  
2653          if (GetExposeInnerGestureFlag()) {
2654              auto pattern = GetPattern();
2655              if (pattern) {
2656                  auto gestureRecognizerJudgeCallback = gestureHub->GetOnGestureRecognizerJudgeBegin();
2657                  pattern->AddInnerOnGestureRecognizerJudgeBegin(std::move(gestureRecognizerJudgeCallback));
2658              }
2659          }
2660      }
2661  }
2662  
TouchTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,TouchRestrict & touchRestrict,TouchTestResult & result,int32_t touchId,ResponseLinkResult & responseLinkResult,bool isDispatch)2663  HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& parentLocalPoint,
2664      const PointF& parentRevertPoint, TouchRestrict& touchRestrict, TouchTestResult& result, int32_t touchId,
2665      ResponseLinkResult& responseLinkResult, bool isDispatch)
2666  {
2667      if (!isActive_ || !eventHub_->IsEnabled()) {
2668          TAG_LOGW(AceLogTag::ACE_UIEVENT, "%{public}s is inActive, need't do touch test", GetTag().c_str());
2669          return HitTestResult::OUT_OF_REGION;
2670      }
2671      auto paintRect = renderContext_->GetPaintRectWithTransform();
2672      auto origRect = renderContext_->GetPaintRectWithoutTransform();
2673      auto localMat = renderContext_->GetLocalTransformMatrix();
2674      if (!touchRestrict.touchEvent.isMouseTouchTest) {
2675          localMat_ = localMat;
2676      }
2677      int32_t parentId = -1;
2678      auto parent = GetAncestorNodeOfFrame();
2679      if (parent) {
2680          parentId = parent->GetId();
2681      }
2682  
2683      if (pattern_->IsResponseRegionExpandingNeededForStylus(touchRestrict.touchEvent)) {
2684          origRect = pattern_->ExpandDefaultResponseRegion(origRect);
2685      }
2686      auto responseRegionList = GetResponseRegionList(origRect, static_cast<int32_t>(touchRestrict.sourceType));
2687      if (SystemProperties::GetDebugEnabled()) {
2688          TAG_LOGD(AceLogTag::ACE_UIEVENT, "TouchTest: point is " SEC_PLD(%{public}s) " in %{public}s, depth: %{public}d",
2689              SEC_PARAM(parentRevertPoint.ToString().c_str()), GetTag().c_str(), GetDepth());
2690          for ([[maybe_unused]] const auto& rect : responseRegionList) {
2691              TAG_LOGD(AceLogTag::ACE_UIEVENT, "TouchTest: responseRegionList is " SEC_PLD(%{public}s)
2692                  ", point is " SEC_PLD(%{public}s),
2693                  SEC_PARAM(rect.ToString().c_str()), SEC_PARAM(parentRevertPoint.ToString().c_str()));
2694          }
2695      }
2696      {
2697          ACE_DEBUG_SCOPED_TRACE("FrameNode::IsOutOfTouchTestRegion");
2698          bool isOutOfRegion = IsOutOfTouchTestRegion(parentRevertPoint, touchRestrict.touchEvent);
2699          AddFrameNodeSnapshot(!isOutOfRegion, parentId, responseRegionList, touchRestrict.touchTestType);
2700          if ((!isDispatch) && isOutOfRegion) {
2701              return HitTestResult::OUT_OF_REGION;
2702          }
2703      }
2704  
2705      RefPtr<TargetComponent> targetComponent;
2706      if (targetComponent_.Upgrade()) {
2707          targetComponent = targetComponent_.Upgrade();
2708      } else {
2709          targetComponent = MakeRefPtr<TargetComponent>();
2710          targetComponent_ = targetComponent;
2711      }
2712      targetComponent->SetNode(WeakClaim(this));
2713  
2714      HitTestResult testResult = HitTestResult::OUT_OF_REGION;
2715      bool preventBubbling = false;
2716      // Child nodes are repackaged into gesture groups (parallel gesture groups, exclusive gesture groups, etc.)
2717      // based on the gesture attributes set by the current parent node (high and low priority, parallel gestures,
2718      // etc.), the newComingTargets is the template object to collect child nodes gesture and used by gestureHub to
2719      // pack gesture group.
2720      TouchTestResult newComingTargets;
2721      auto tmp = parentLocalPoint - paintRect.GetOffset();
2722      auto preLocation = tmp;
2723      renderContext_->GetPointWithTransform(tmp);
2724      const auto localPoint = tmp;
2725      auto localTransformOffset = preLocation - localPoint;
2726  
2727      auto revertPoint = parentRevertPoint;
2728      MapPointTo(revertPoint, GetOrRefreshRevertMatrixFromCache());
2729      auto subRevertPoint = revertPoint - origRect.GetOffset();
2730      bool consumed = false;
2731  
2732      HitTestMode onTouchInterceptresult = HitTestMode::HTMDEFAULT;
2733      if (touchRestrict.inputEventType != InputEventType::MOUSE_BUTTON) {
2734          onTouchInterceptresult = TriggerOnTouchIntercept(touchRestrict.touchEvent);
2735      }
2736      TouchResult touchRes;
2737      if (onTouchInterceptresult != HitTestMode::HTMBLOCK) {
2738          std::vector<TouchTestInfo> touchInfos;
2739          CollectTouchInfos(globalPoint, subRevertPoint, touchInfos);
2740          touchRes = GetOnChildTouchTestRet(touchInfos);
2741          if ((touchRes.strategy != TouchTestStrategy::DEFAULT) && touchRes.id.empty()) {
2742              TAG_LOGW(AceLogTag::ACE_UIEVENT, "onChildTouchTest result is: "
2743                  "id = " SEC_PLD(%{public}s) ", strategy = %{public}d.",
2744                  SEC_PARAM(touchRes.id.c_str()), static_cast<int32_t>(touchRes.strategy));
2745              touchRes.strategy = TouchTestStrategy::DEFAULT;
2746          }
2747  
2748          auto childNode = GetDispatchFrameNode(touchRes);
2749          if (childNode != nullptr) {
2750              TAG_LOGD(AceLogTag::ACE_UIEVENT, SEC_PLD(%{public}s) " do TouchTest, parameter isDispatch is true.",
2751                  SEC_PARAM(childNode->GetInspectorId()->c_str()));
2752              auto hitResult = childNode->TouchTest(globalPoint, localPoint, subRevertPoint, touchRestrict,
2753                  newComingTargets, touchId, responseLinkResult, true);
2754              if (touchRes.strategy == TouchTestStrategy::FORWARD ||
2755                  touchRes.strategy == TouchTestStrategy::FORWARD_COMPETITION) {
2756                  touchRestrict.childTouchTestList.emplace_back(touchRes.id);
2757              }
2758              if (hitResult == HitTestResult::STOP_BUBBLING) {
2759                  preventBubbling = true;
2760                  consumed = true;
2761              }
2762  
2763              if (hitResult == HitTestResult::BUBBLING) {
2764                  consumed = true;
2765              }
2766          }
2767      }
2768  
2769      for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
2770          if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
2771              break;
2772          }
2773          if (onTouchInterceptresult != HitTestMode::HTMBLOCK) {
2774              if (touchRes.strategy == TouchTestStrategy::FORWARD) {
2775                  break;
2776              }
2777          }
2778  
2779          const auto& child = iter->Upgrade();
2780          if (!child) {
2781              continue;
2782          }
2783          if (onTouchInterceptresult != HitTestMode::HTMBLOCK) {
2784              std::string id;
2785              if (child->GetInspectorId().has_value()) {
2786                  id = child->GetInspectorId().value();
2787              }
2788              if (touchRes.strategy == TouchTestStrategy::FORWARD_COMPETITION && touchRes.id == id) {
2789                  continue;
2790              }
2791          }
2792  
2793          auto childHitResult = child->TouchTest(
2794              globalPoint, localPoint, subRevertPoint, touchRestrict, newComingTargets, touchId, responseLinkResult);
2795          if (childHitResult == HitTestResult::STOP_BUBBLING) {
2796              preventBubbling = true;
2797              consumed = true;
2798              if ((child->GetHitTestMode() == HitTestMode::HTMBLOCK) ||
2799                  (child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
2800                  (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
2801                  ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && IsExclusiveEventForChild())) {
2802                  break;
2803              }
2804          }
2805  
2806          // In normal process, the node block the brother node.
2807          if (childHitResult == HitTestResult::BUBBLING &&
2808              ((child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
2809                  (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
2810                  ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && IsExclusiveEventForChild()))) {
2811              consumed = true;
2812              break;
2813          }
2814      }
2815  
2816      AddJudgeToTargetComponent(targetComponent);
2817  
2818      // first update HitTestResult by children status.
2819      if (consumed) {
2820          testResult = preventBubbling ? HitTestResult::STOP_BUBBLING : HitTestResult::BUBBLING;
2821          consumed = false;
2822      } else if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
2823          testResult = HitTestResult::STOP_BUBBLING;
2824      }
2825  
2826      if (!preventBubbling && (GetHitTestMode() != HitTestMode::HTMNONE) &&
2827          (isDispatch || (InResponseRegionList(revertPoint, responseRegionList)))) {
2828          pattern_->OnTouchTestHit(touchRestrict.hitTestType);
2829          consumed = true;
2830          if (touchRestrict.hitTestType == SourceType::TOUCH) {
2831              auto gestureHub = eventHub_->GetGestureEventHub();
2832              if (gestureHub) {
2833                  TouchTestResult finalResult;
2834                  ResponseLinkResult newComingResponseLinkTargets;
2835                  const auto coordinateOffset = globalPoint - localPoint - localTransformOffset;
2836                  preventBubbling = gestureHub->ProcessTouchTestHit(coordinateOffset, touchRestrict, newComingTargets,
2837                      finalResult, touchId, localPoint, targetComponent, newComingResponseLinkTargets);
2838                  newComingTargets.swap(finalResult);
2839                  TriggerShouldParallelInnerWith(newComingResponseLinkTargets, responseLinkResult);
2840                  responseLinkResult.splice(responseLinkResult.end(), std::move(newComingResponseLinkTargets));
2841              }
2842          } else if (touchRestrict.hitTestType == SourceType::MOUSE) {
2843              preventBubbling = ProcessMouseTestHit(globalPoint, localPoint, touchRestrict, newComingTargets);
2844          }
2845      }
2846  
2847      result.splice(result.end(), std::move(newComingTargets));
2848      if (touchRestrict.hitTestType == SourceType::TOUCH) {
2849          // combine into exclusive recognizer group.
2850          auto gestureHub = eventHub_->GetGestureEventHub();
2851          if (gestureHub) {
2852              gestureHub->CombineIntoExclusiveRecognizer(globalPoint, localPoint, result, touchId);
2853          }
2854      }
2855  
2856      // consumed by children and return result.
2857      if (!consumed) {
2858          return testResult;
2859      }
2860  
2861      if (testResult == HitTestResult::OUT_OF_REGION) {
2862          // consume only by self.
2863          if (preventBubbling) {
2864              return HitTestResult::STOP_BUBBLING;
2865          }
2866          return (GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ? HitTestResult::SELF_TRANSPARENT
2867                                                                        : HitTestResult::BUBBLING;
2868      }
2869      // consume by self and children.
2870      return testResult;
2871  }
2872  
ProcessMouseTestHit(const PointF & globalPoint,const PointF & localPoint,TouchRestrict & touchRestrict,TouchTestResult & newComingTargets)2873  bool FrameNode::ProcessMouseTestHit(const PointF& globalPoint, const PointF& localPoint,
2874      TouchRestrict& touchRestrict, TouchTestResult& newComingTargets)
2875  {
2876      auto mouseHub = eventHub_->GetInputEventHub();
2877      if (!mouseHub) {
2878          return false;
2879      }
2880  
2881      const auto coordinateOffset = globalPoint - localPoint;
2882      if (touchRestrict.touchEvent.IsPenHoverEvent()) {
2883          return mouseHub->ProcessPenHoverTestHit(coordinateOffset, newComingTargets);
2884      }
2885  
2886      return mouseHub->ProcessMouseTestHit(coordinateOffset, newComingTargets);
2887  }
2888  
GetResponseRegionList(const RectF & rect,int32_t sourceType)2889  std::vector<RectF> FrameNode::GetResponseRegionList(const RectF& rect, int32_t sourceType)
2890  {
2891      std::vector<RectF> responseRegionList;
2892      auto gestureHub = eventHub_->GetGestureEventHub();
2893      if (!gestureHub) {
2894          responseRegionList.emplace_back(rect);
2895          return responseRegionList;
2896      }
2897      auto scaleProperty = ScaleProperty::CreateScaleProperty();
2898      bool isMouseEvent = (static_cast<SourceType>(sourceType) == SourceType::MOUSE);
2899      if (isMouseEvent) {
2900          if (gestureHub->GetResponseRegion().empty() && (gestureHub->GetMouseResponseRegion().empty())) {
2901              responseRegionList.emplace_back(rect);
2902              return responseRegionList;
2903          }
2904      } else {
2905          if (gestureHub->GetResponseRegion().empty()) {
2906              responseRegionList.emplace_back(rect);
2907              return responseRegionList;
2908          }
2909      }
2910  
2911      if (isMouseEvent && (!gestureHub->GetMouseResponseRegion().empty())) {
2912          for (const auto& region : gestureHub->GetMouseResponseRegion()) {
2913              auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
2914              auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
2915              auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
2916              auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
2917              if (!x.has_value() || !y.has_value() || !width.has_value() || !height.has_value()) {
2918                  continue;
2919              }
2920              RectF mouseRegion(rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(),
2921                  height.value());
2922              responseRegionList.emplace_back(mouseRegion);
2923          }
2924          return responseRegionList;
2925      }
2926      for (const auto& region : gestureHub->GetResponseRegion()) {
2927          auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
2928          auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
2929          auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
2930          auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
2931          if (!x.has_value() || !y.has_value() || !width.has_value() || !height.has_value()) {
2932              continue;
2933          }
2934          RectF responseRegion(
2935              rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(), height.value());
2936          responseRegionList.emplace_back(responseRegion);
2937      }
2938      return responseRegionList;
2939  }
2940  
GetResponseRegionListForRecognizer(int32_t sourceType)2941  std::vector<RectF> FrameNode::GetResponseRegionListForRecognizer(int32_t sourceType)
2942  {
2943      auto paintRect = renderContext_->GetPaintRectWithoutTransform();
2944      auto responseRegionList = GetResponseRegionList(paintRect, sourceType);
2945      return responseRegionList;
2946  }
2947  
GetResponseRegionListForTouch(const RectF & rect)2948  std::vector<RectF> FrameNode::GetResponseRegionListForTouch(const RectF& rect)
2949  {
2950      ACE_LAYOUT_TRACE_BEGIN("GetResponseRegionListForTouch");
2951      std::vector<RectF> responseRegionList;
2952      auto gestureHub = eventHub_->GetGestureEventHub();
2953      if (!gestureHub) {
2954          ACE_LAYOUT_TRACE_END()
2955          return responseRegionList;
2956      }
2957  
2958      bool isAccessibilityClickable = gestureHub->IsAccessibilityClickable();
2959      if (!isAccessibilityClickable) {
2960          ACE_LAYOUT_TRACE_END()
2961          return responseRegionList;
2962      }
2963      auto offset = GetPositionToScreen();
2964      if (gestureHub->GetResponseRegion().empty()) {
2965          RectF rectToScreen{round(offset.GetX()), round(offset.GetY()), round(rect.Width()), round(rect.Height())};
2966          responseRegionList.emplace_back(rectToScreen);
2967          ACE_LAYOUT_TRACE_END()
2968          return responseRegionList;
2969      }
2970  
2971      auto scaleProperty = ScaleProperty::CreateScaleProperty();
2972      for (const auto& region : gestureHub->GetResponseRegion()) {
2973          auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
2974          auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
2975          auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
2976          auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
2977          RectF responseRegion(round(offset.GetX() + x.value()), round(offset.GetY() + y.value()),
2978              round(width.value()), round(height.value()));
2979          responseRegionList.emplace_back(responseRegion);
2980      }
2981      ACE_LAYOUT_TRACE_END()
2982      return responseRegionList;
2983  }
2984  
GetResponseRegionListByTraversal(std::vector<RectF> & responseRegionList)2985  void FrameNode::GetResponseRegionListByTraversal(std::vector<RectF>& responseRegionList)
2986  {
2987      CHECK_NULL_VOID(renderContext_);
2988      auto origRect = renderContext_->GetPaintRectWithoutTransform();
2989      auto pipelineContext = GetContext();
2990      CHECK_NULL_VOID(pipelineContext);
2991      auto offset = GetPositionToScreen();
2992      RectF rectToScreen{offset.GetX(), offset.GetY(), origRect.Width(), origRect.Height()};
2993      auto window = pipelineContext->GetCurrentWindowRect();
2994      RectF windowRect{window.Left(), window.Top(), window.Width(), window.Height()};
2995  
2996      if (rectToScreen.Left() >= windowRect.Right() || rectToScreen.Right() <= windowRect.Left() ||
2997          rectToScreen.Top() >= windowRect.Bottom() || rectToScreen.Bottom() <= windowRect.Top()) {
2998          return;
2999      }
3000  
3001      auto rootRegionList = GetResponseRegionListForTouch(origRect);
3002      if (!rootRegionList.empty()) {
3003          for (auto rect : rootRegionList) {
3004              responseRegionList.push_back(rect.IntersectRectT(windowRect));
3005          }
3006          return;
3007      }
3008      for (auto childWeak = frameChildren_.rbegin(); childWeak != frameChildren_.rend(); ++childWeak) {
3009          const auto& child = childWeak->Upgrade();
3010          if (!child) {
3011              continue;
3012          }
3013          child->GetResponseRegionListByTraversal(responseRegionList);
3014      }
3015  }
3016  
InResponseRegionList(const PointF & parentLocalPoint,const std::vector<RectF> & responseRegionList) const3017  bool FrameNode::InResponseRegionList(const PointF& parentLocalPoint, const std::vector<RectF>& responseRegionList) const
3018  {
3019      for (const auto& rect : responseRegionList) {
3020          if (rect.IsInRegion(parentLocalPoint)) {
3021              return true;
3022          }
3023      }
3024      return false;
3025  }
3026  
MouseTest(const PointF & globalPoint,const PointF & parentLocalPoint,MouseTestResult & onMouseResult,MouseTestResult & onHoverResult,RefPtr<FrameNode> & hoverNode)3027  HitTestResult FrameNode::MouseTest(const PointF& globalPoint, const PointF& parentLocalPoint,
3028      MouseTestResult& onMouseResult, MouseTestResult& onHoverResult, RefPtr<FrameNode>& hoverNode)
3029  {
3030      // unuseable function. do nothing.
3031      return HitTestResult::BUBBLING;
3032  }
3033  
CheckChildHitTestReslut(HitTestResult childHitResult,const RefPtr<OHOS::Ace::NG::FrameNode> & child,bool & preventBubbling,bool & consumed,bool isExclusiveEventForChild)3034  bool CheckChildHitTestReslut(HitTestResult childHitResult, const RefPtr<OHOS::Ace::NG::FrameNode>& child,
3035      bool& preventBubbling, bool& consumed, bool isExclusiveEventForChild)
3036  {
3037      consumed = false;
3038      if (childHitResult == HitTestResult::STOP_BUBBLING) {
3039          preventBubbling = true;
3040          consumed = true;
3041          return ((child->GetHitTestMode() == HitTestMode::HTMBLOCK) ||
3042                  (child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
3043                  (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
3044                  ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && isExclusiveEventForChild));
3045      } else if (childHitResult == HitTestResult::BUBBLING) {
3046          consumed = true;
3047          return ((child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
3048                  (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
3049                  ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && isExclusiveEventForChild));
3050      }
3051      return false;
3052  }
3053  
3054  
AxisTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,TouchRestrict & touchRestrict,AxisTestResult & axisResult)3055  HitTestResult FrameNode::AxisTest(const PointF& globalPoint, const PointF& parentLocalPoint,
3056      const PointF& parentRevertPoint, TouchRestrict& touchRestrict, AxisTestResult& axisResult)
3057  {
3058      if (!isActive_ || !eventHub_->IsEnabled()) {
3059          TAG_LOGW(AceLogTag::ACE_UIEVENT, "%{public}s is inActive, need't do touch test", GetTag().c_str());
3060          return HitTestResult::OUT_OF_REGION;
3061      }
3062      {
3063          ACE_DEBUG_SCOPED_TRACE("FrameNode::IsOutOfTouchTestRegion");
3064          if (IsOutOfTouchTestRegion(parentRevertPoint, touchRestrict.touchEvent)) {
3065              return HitTestResult::OUT_OF_REGION;
3066          }
3067      }
3068      HitTestResult testResult = HitTestResult::OUT_OF_REGION;
3069      bool preventBubbling = false;
3070      AxisTestResult newComingTargets;
3071      auto localPoint = parentLocalPoint - renderContext_->GetPaintRectWithTransform().GetOffset();
3072      renderContext_->GetPointWithTransform(localPoint);
3073      auto revertPoint = parentRevertPoint;
3074      MapPointTo(revertPoint, GetOrRefreshRevertMatrixFromCache());
3075      auto subRevertPoint = revertPoint - renderContext_->GetPaintRectWithoutTransform().GetOffset();
3076      bool consumed = false;
3077      for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
3078          if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
3079              break;
3080          }
3081          const auto& child = iter->Upgrade();
3082          if (!child) {
3083              continue;
3084          }
3085          auto childHitResult = child->AxisTest(globalPoint, localPoint, subRevertPoint, touchRestrict, newComingTargets);
3086          if (CheckChildHitTestReslut(childHitResult, child, preventBubbling, consumed, IsExclusiveEventForChild())) {
3087              break;
3088          }
3089      }
3090      CollectSelfAxisResult(
3091          globalPoint, localPoint, consumed, revertPoint, axisResult, preventBubbling, testResult, touchRestrict);
3092  
3093      axisResult.splice(axisResult.end(), std::move(newComingTargets));
3094      if (!consumed) {
3095          return testResult;
3096      }
3097      if (testResult == HitTestResult::OUT_OF_REGION && preventBubbling) {
3098          return HitTestResult::STOP_BUBBLING;
3099      } else {
3100          return (GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ? HitTestResult::SELF_TRANSPARENT
3101                                                                        : HitTestResult::BUBBLING;
3102      }
3103      return testResult;
3104  }
3105  
CollectSelfAxisResult(const PointF & globalPoint,const PointF & localPoint,bool & consumed,const PointF & parentRevertPoint,AxisTestResult & axisResult,bool & preventBubbling,HitTestResult & testResult,TouchRestrict & touchRestrict)3106  void FrameNode::CollectSelfAxisResult(const PointF& globalPoint, const PointF& localPoint, bool& consumed,
3107      const PointF& parentRevertPoint, AxisTestResult& axisResult, bool& preventBubbling, HitTestResult& testResult,
3108      TouchRestrict& touchRestrict)
3109  {
3110      if (consumed) {
3111          testResult = preventBubbling ? HitTestResult::STOP_BUBBLING : HitTestResult::BUBBLING;
3112          consumed = false;
3113      } else if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
3114          testResult = HitTestResult::STOP_BUBBLING;
3115      }
3116      auto origRect = renderContext_->GetPaintRectWithoutTransform();
3117      auto resRegionList = GetResponseRegionList(origRect, static_cast<int32_t>(touchRestrict.touchEvent.sourceType));
3118      if (SystemProperties::GetDebugEnabled()) {
3119          TAG_LOGD(AceLogTag::ACE_UIEVENT, "AxisTest: point is %{public}s in %{public}s, depth: %{public}d",
3120              parentRevertPoint.ToString().c_str(), GetTag().c_str(), GetDepth());
3121          for (const auto& rect : resRegionList) {
3122              TAG_LOGD(AceLogTag::ACE_UIEVENT, "AxisTest: resRegionList is %{public}s, point is %{public}s",
3123                  rect.ToString().c_str(), parentRevertPoint.ToString().c_str());
3124          }
3125      }
3126      if (preventBubbling) {
3127          return;
3128      }
3129      if (GetHitTestMode() == HitTestMode::HTMNONE) {
3130          return;
3131      }
3132      if (InResponseRegionList(parentRevertPoint, resRegionList)) {
3133          consumed = true;
3134          auto inputHub = eventHub_->GetInputEventHub();
3135          if (inputHub) {
3136              const auto coordinateOffset = globalPoint - localPoint;
3137              inputHub->ProcessAxisTestHit(coordinateOffset, axisResult);
3138          }
3139      }
3140  }
3141  
AnimateHoverEffect(bool isHovered) const3142  void FrameNode::AnimateHoverEffect(bool isHovered) const
3143  {
3144      auto renderContext = GetRenderContext();
3145      if (!renderContext) {
3146          return;
3147      }
3148      HoverEffectType animationType = HoverEffectType::UNKNOWN;
3149      auto inputEventHub = eventHub_->GetInputEventHub();
3150      if (inputEventHub) {
3151          animationType = inputEventHub->GetHoverEffect();
3152          if (animationType == HoverEffectType::UNKNOWN || animationType == HoverEffectType::AUTO) {
3153              animationType = inputEventHub->GetHoverEffectAuto();
3154          }
3155      }
3156      if (animationType == HoverEffectType::SCALE) {
3157          renderContext->AnimateHoverEffectScale(isHovered);
3158      } else if (animationType == HoverEffectType::BOARD) {
3159          renderContext->AnimateHoverEffectBoard(isHovered);
3160      }
3161  }
3162  
GetOrCreateFocusHub() const3163  RefPtr<FocusHub> FrameNode::GetOrCreateFocusHub() const
3164  {
3165      if (!pattern_) {
3166          return eventHub_->GetOrCreateFocusHub();
3167      }
3168      auto focusPattern = pattern_->GetFocusPattern();
3169      return eventHub_->GetOrCreateFocusHub(focusPattern);
3170  }
3171  
OnWindowShow()3172  void FrameNode::OnWindowShow()
3173  {
3174      pattern_->OnWindowShow();
3175  }
3176  
OnWindowHide()3177  void FrameNode::OnWindowHide()
3178  {
3179      pattern_->OnWindowHide();
3180  }
3181  
OnWindowFocused()3182  void FrameNode::OnWindowFocused()
3183  {
3184      if (renderContext_) {
3185          renderContext_->UpdateWindowFocusState(true);
3186      }
3187      pattern_->OnWindowFocused();
3188  }
3189  
OnWindowUnfocused()3190  void FrameNode::OnWindowUnfocused()
3191  {
3192      if (renderContext_) {
3193          renderContext_->UpdateWindowFocusState(false);
3194      }
3195      pattern_->OnWindowUnfocused();
3196  }
3197  
ContextPositionConvertToPX(const RefPtr<RenderContext> & context,const SizeF & percentReference)3198  std::pair<float, float> FrameNode::ContextPositionConvertToPX(
3199      const RefPtr<RenderContext>& context, const SizeF& percentReference)
3200  {
3201      std::pair<float, float> position;
3202      CHECK_NULL_RETURN(context, position);
3203      auto scaleProperty = ScaleProperty::CreateScaleProperty();
3204      position.first =
3205          ConvertToPx(context->GetPositionProperty()->GetPosition()->GetX(), scaleProperty, percentReference.Width())
3206              .value_or(0.0);
3207      position.second =
3208          ConvertToPx(context->GetPositionProperty()->GetPosition()->GetY(), scaleProperty, percentReference.Height())
3209              .value_or(0.0);
3210      return position;
3211  }
3212  
OnPixelRoundFinish(const SizeF & pixelGridRoundSize)3213  void FrameNode::OnPixelRoundFinish(const SizeF& pixelGridRoundSize)
3214  {
3215      CHECK_NULL_VOID(pattern_);
3216      pattern_->OnPixelRoundFinish(pixelGridRoundSize);
3217  }
3218  
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)3219  void FrameNode::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
3220  {
3221      pattern_->OnWindowSizeChanged(width, height, type);
3222  }
3223  
3224  /* @deprecated  This func will be deleted, please use GetTransformRelativeOffset() instead. */
GetOffsetRelativeToWindow() const3225  OffsetF FrameNode::GetOffsetRelativeToWindow() const
3226  {
3227      auto offset = geometryNode_->GetFrameOffset();
3228      auto parent = GetAncestorNodeOfFrame(true);
3229      if (renderContext_ && renderContext_->GetPositionProperty()) {
3230          if (renderContext_->GetPositionProperty()->HasPosition()) {
3231              auto renderPosition =
3232                  ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
3233              offset.SetX(static_cast<float>(renderPosition.first));
3234              offset.SetY(static_cast<float>(renderPosition.second));
3235          }
3236      }
3237      while (parent) {
3238          auto parentRenderContext = parent->GetRenderContext();
3239          if (parentRenderContext && parentRenderContext->GetPositionProperty()) {
3240              if (parentRenderContext->GetPositionProperty()->HasPosition()) {
3241                  auto parentLayoutProperty = parent->GetLayoutProperty();
3242                  CHECK_NULL_RETURN(parentLayoutProperty, offset);
3243                  auto parentRenderContextPosition = ContextPositionConvertToPX(
3244                      parentRenderContext, parentLayoutProperty->GetLayoutConstraint()->percentReference);
3245                  offset.AddX(static_cast<float>(parentRenderContextPosition.first));
3246                  offset.AddY(static_cast<float>(parentRenderContextPosition.second));
3247                  parent = parent->GetAncestorNodeOfFrame(true);
3248                  continue;
3249              }
3250          }
3251          if (parentRenderContext) {
3252              offset += parentRenderContext->GetPaintRectWithoutTransform().GetOffset();
3253          }
3254          parent = parent->GetAncestorNodeOfFrame(true);
3255      }
3256  
3257      return offset;
3258  }
3259  
GetPositionToScreen()3260  OffsetF FrameNode::GetPositionToScreen()
3261  {
3262      auto offsetCurrent = GetOffsetRelativeToWindow();
3263      auto pipelineContext = GetContext();
3264      CHECK_NULL_RETURN(pipelineContext, OffsetF());
3265      auto windowOffset = pipelineContext->GetCurrentWindowRect().GetOffset();
3266      OffsetF offset(windowOffset.GetX() + offsetCurrent.GetX(), windowOffset.GetY() + offsetCurrent.GetY());
3267      return offset;
3268  }
3269  
GetPositionToParentWithTransform() const3270  OffsetF FrameNode::GetPositionToParentWithTransform() const
3271  {
3272      auto context = GetRenderContext();
3273      CHECK_NULL_RETURN(context, OffsetF());
3274      auto offset = context->GetPaintRectWithoutTransform().GetOffset();
3275      PointF pointTmp(offset.GetX(), offset.GetY());
3276      context->GetPointTransformRotate(pointTmp);
3277      offset.SetX(pointTmp.GetX());
3278      offset.SetY(pointTmp.GetY());
3279      return offset;
3280  }
3281  
GetPositionToScreenWithTransform()3282  OffsetF FrameNode::GetPositionToScreenWithTransform()
3283  {
3284      auto pipelineContext = GetContext();
3285      CHECK_NULL_RETURN(pipelineContext, OffsetF());
3286      auto windowOffset = pipelineContext->GetCurrentWindowRect().GetOffset();
3287      OffsetF nodeOffset = GetPositionToWindowWithTransform();
3288      OffsetF offset(windowOffset.GetX() + nodeOffset.GetX(), windowOffset.GetY() + nodeOffset.GetY());
3289      return offset;
3290  }
3291  
GetPositionToWindowWithTransform(bool fromBottom) const3292  OffsetF FrameNode::GetPositionToWindowWithTransform(bool fromBottom) const
3293  {
3294      auto context = GetRenderContext();
3295      CHECK_NULL_RETURN(context, OffsetF());
3296      auto rect = context->GetPaintRectWithoutTransform();
3297      OffsetF offset;
3298      if (!fromBottom) {
3299          offset = rect.GetOffset();
3300      } else {
3301          OffsetF offsetBottom(rect.GetX() + rect.Width(), rect.GetY() + rect.Height());
3302          offset = offsetBottom;
3303      }
3304      PointF pointNode(offset.GetX(), offset.GetY());
3305      context->GetPointTransformRotate(pointNode);
3306      auto parent = GetAncestorNodeOfFrame(true);
3307      while (parent) {
3308          auto parentRenderContext = parent->GetRenderContext();
3309          offset = parentRenderContext->GetPaintRectWithoutTransform().GetOffset();
3310          PointF pointTmp(offset.GetX() + pointNode.GetX(), offset.GetY() + pointNode.GetY());
3311          parentRenderContext->GetPointTransformRotate(pointTmp);
3312          pointNode.SetX(pointTmp.GetX());
3313          pointNode.SetY(pointTmp.GetY());
3314          parent = parent->GetAncestorNodeOfFrame(true);
3315      }
3316      offset.SetX(pointNode.GetX());
3317      offset.SetY(pointNode.GetY());
3318      return offset;
3319  }
3320  
GetTransformRectRelativeToWindow() const3321  RectF FrameNode::GetTransformRectRelativeToWindow() const
3322  {
3323      auto context = GetRenderContext();
3324      CHECK_NULL_RETURN(context, RectF());
3325      RectF rect = context->GetPaintRectWithTransform();
3326      auto parent = GetAncestorNodeOfFrame(true);
3327      while (parent) {
3328          rect = ApplyFrameNodeTranformToRect(rect, parent);
3329          parent = parent->GetAncestorNodeOfFrame(true);
3330      }
3331      return rect;
3332  }
3333  
GetTransformRelativeOffset() const3334  OffsetF FrameNode::GetTransformRelativeOffset() const
3335  {
3336      auto context = GetRenderContext();
3337      CHECK_NULL_RETURN(context, OffsetF());
3338      auto offset = context->GetPaintRectWithTransform().GetOffset();
3339      auto parent = GetAncestorNodeOfFrame(true);
3340  
3341      while (parent) {
3342          auto parentRenderContext = parent->GetRenderContext();
3343          offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
3344          parent = parent->GetAncestorNodeOfFrame(true);
3345      }
3346  
3347      return offset;
3348  }
3349  
GetPaintRectOffset(bool excludeSelf) const3350  OffsetF FrameNode::GetPaintRectOffset(bool excludeSelf) const
3351  {
3352      auto context = GetRenderContext();
3353      CHECK_NULL_RETURN(context, OffsetF());
3354      OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithTransform().GetOffset();
3355      auto parent = GetAncestorNodeOfFrame();
3356      while (parent) {
3357          auto renderContext = parent->GetRenderContext();
3358          CHECK_NULL_RETURN(renderContext, OffsetF());
3359          offset += renderContext->GetPaintRectWithTransform().GetOffset();
3360          parent = parent->GetAncestorNodeOfFrame();
3361      }
3362      return offset;
3363  }
3364  
GetPaintRectOffsetNG(bool excludeSelf) const3365  OffsetF FrameNode::GetPaintRectOffsetNG(bool excludeSelf) const
3366  {
3367      auto context = GetRenderContext();
3368      CHECK_NULL_RETURN(context, OffsetF());
3369      OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithoutTransform().GetOffset();
3370      Point point = Matrix4::Invert(context->GetRevertMatrix()) * Point(offset.GetX(), offset.GetY());
3371      auto parent = GetAncestorNodeOfFrame();
3372      while (parent) {
3373          auto renderContext = parent->GetRenderContext();
3374          CHECK_NULL_RETURN(renderContext, OffsetF());
3375          auto parentOffset = renderContext->GetPaintRectWithoutTransform().GetOffset();
3376          point = point + Offset(parentOffset.GetX(), parentOffset.GetY());
3377          auto parentMatrix = Matrix4::Invert(renderContext->GetRevertMatrix());
3378          point = parentMatrix * point;
3379          parent = parent->GetAncestorNodeOfFrame();
3380      }
3381      return OffsetF(point.GetX(), point.GetY());
3382  }
3383  
GetRectPoints(SizeF & frameSize)3384  std::vector<Point> GetRectPoints(SizeF& frameSize)
3385  {
3386      std::vector<Point> pointList;
3387      pointList.push_back(Point(0, 0));
3388      pointList.push_back(Point(frameSize.Width(), 0));
3389      pointList.push_back(Point(0, frameSize.Height()));
3390      pointList.push_back(Point(frameSize.Width(), frameSize.Height()));
3391      return pointList;
3392  }
3393  
GetBoundingBox(std::vector<Point> & pointList)3394  RectF GetBoundingBox(std::vector<Point>& pointList)
3395  {
3396      Point pMax = pointList[0];
3397      Point pMin = pointList[0];
3398  
3399      for (auto &point: pointList) {
3400          if (point.GetX() > pMax.GetX()) {
3401              pMax.SetX(point.GetX());
3402          }
3403          if (point.GetX() < pMin.GetX()) {
3404              pMin.SetX(point.GetX());
3405          }
3406          if (point.GetY() > pMax.GetY()) {
3407              pMax.SetY(point.GetY());
3408          }
3409          if (point.GetY() < pMin.GetY()) {
3410              pMin.SetY(point.GetY());
3411          }
3412      }
3413      return RectF(pMin.GetX(), pMin.GetY(), pMax.GetX() - pMin.GetX(), pMax.GetY() - pMin.GetY());
3414  }
3415  
GetRectPointToParentWithTransform(std::vector<Point> & pointList,const RefPtr<FrameNode> & parent) const3416  bool FrameNode::GetRectPointToParentWithTransform(std::vector<Point>& pointList, const RefPtr<FrameNode>& parent) const
3417  {
3418      auto renderContext = parent->GetRenderContext();
3419      CHECK_NULL_RETURN(renderContext, false);
3420      auto parentOffset = renderContext->GetPaintRectWithoutTransform().GetOffset();
3421      auto parentMatrix = Matrix4::Invert(renderContext->GetRevertMatrix());
3422      for (auto& point: pointList) {
3423          point = point + Offset(parentOffset.GetX(), parentOffset.GetY());
3424          point = parentMatrix * point;
3425      }
3426      return true;
3427  }
3428  
GetPaintRectToWindowWithTransform()3429  RectF FrameNode::GetPaintRectToWindowWithTransform()
3430  {
3431      auto context = GetRenderContext();
3432      CHECK_NULL_RETURN(context, RectF());
3433      auto geometryNode = GetGeometryNode();
3434      CHECK_NULL_RETURN(geometryNode, RectF());
3435      auto frameSize = geometryNode->GetFrameSize();
3436      auto pointList = GetRectPoints(frameSize);
3437      GetRectPointToParentWithTransform(pointList, Claim(this));
3438      auto parent = GetAncestorNodeOfFrame();
3439      while (parent) {
3440          if (GetRectPointToParentWithTransform(pointList, parent)) {
3441              parent = parent->GetAncestorNodeOfFrame();
3442          } else {
3443              return RectF();
3444          }
3445      }
3446      return GetBoundingBox(pointList);
3447  }
3448  
GetPaintRectCenter(bool checkWindowBoundary) const3449  OffsetF FrameNode::GetPaintRectCenter(bool checkWindowBoundary) const
3450  {
3451      auto context = GetRenderContext();
3452      CHECK_NULL_RETURN(context, OffsetF());
3453      auto paintRect = context->GetPaintRectWithoutTransform();
3454      auto offset = paintRect.GetOffset();
3455      PointF pointNode(offset.GetX() + paintRect.Width() / 2.0f, offset.GetY() + paintRect.Height() / 2.0f);
3456      context->GetPointTransformRotate(pointNode);
3457      auto parent = GetAncestorNodeOfFrame();
3458      while (parent) {
3459          if (checkWindowBoundary && parent->IsWindowBoundary()) {
3460              break;
3461          }
3462          auto renderContext = parent->GetRenderContext();
3463          CHECK_NULL_RETURN(renderContext, OffsetF());
3464          offset = renderContext->GetPaintRectWithoutTransform().GetOffset();
3465          pointNode.SetX(offset.GetX() + pointNode.GetX());
3466          pointNode.SetY(offset.GetY() + pointNode.GetY());
3467          renderContext->GetPointTransformRotate(pointNode);
3468          parent = parent->GetAncestorNodeOfFrame();
3469      }
3470      return OffsetF(pointNode.GetX(), pointNode.GetY());
3471  }
3472  
GetParentGlobalOffsetDuringLayout() const3473  OffsetF FrameNode::GetParentGlobalOffsetDuringLayout() const
3474  {
3475      OffsetF offset {};
3476      auto parent = GetAncestorNodeOfFrame();
3477      while (parent) {
3478          offset += parent->geometryNode_->GetFrameOffset();
3479          parent = parent->GetAncestorNodeOfFrame();
3480      }
3481      return offset;
3482  }
3483  
GetPaintRectGlobalOffsetWithTranslate(bool excludeSelf) const3484  std::pair<OffsetF, bool> FrameNode::GetPaintRectGlobalOffsetWithTranslate(bool excludeSelf) const
3485  {
3486      bool error = false;
3487      auto context = GetRenderContext();
3488      CHECK_NULL_RETURN(context, std::make_pair(OffsetF(), error));
3489      OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithTranslate().first.GetOffset();
3490      auto parent = GetAncestorNodeOfFrame();
3491      while (parent) {
3492          auto renderContext = parent->GetRenderContext();
3493          CHECK_NULL_RETURN(renderContext, std::make_pair(OffsetF(), error));
3494          auto [rect, err] = renderContext->GetPaintRectWithTranslate();
3495          error = error || err;
3496          CHECK_NULL_RETURN(rect.IsValid(), std::make_pair(offset + parent->GetPaintRectOffset(), error));
3497          offset += rect.GetOffset();
3498          parent = parent->GetAncestorNodeOfFrame();
3499      }
3500      return std::make_pair(offset, error);
3501  }
3502  
GetPaintRectOffsetToPage() const3503  OffsetF FrameNode::GetPaintRectOffsetToPage() const
3504  {
3505      auto context = GetRenderContext();
3506      CHECK_NULL_RETURN(context, OffsetF());
3507      OffsetF offset = context->GetPaintRectWithTransform().GetOffset();
3508      auto parent = GetAncestorNodeOfFrame();
3509      while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
3510          auto renderContext = parent->GetRenderContext();
3511          CHECK_NULL_RETURN(renderContext, OffsetF());
3512          offset += renderContext->GetPaintRectWithTransform().GetOffset();
3513          parent = parent->GetAncestorNodeOfFrame();
3514      }
3515      return (parent && parent->GetTag() == V2::PAGE_ETS_TAG) ? offset : OffsetF();
3516  }
3517  
GetViewPort() const3518  std::optional<RectF> FrameNode::GetViewPort() const
3519  {
3520      if (viewPort_.has_value()) {
3521          return viewPort_;
3522      }
3523      auto parent = GetAncestorNodeOfFrame();
3524      while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
3525          auto parentViewPort = parent->GetSelfViewPort();
3526          if (parentViewPort.has_value()) {
3527              return parentViewPort;
3528          }
3529          parent = parent->GetAncestorNodeOfFrame();
3530      }
3531      return std::nullopt;
3532  }
3533  
OnNotifyMemoryLevel(int32_t level)3534  void FrameNode::OnNotifyMemoryLevel(int32_t level)
3535  {
3536      pattern_->OnNotifyMemoryLevel(level);
3537  }
3538  
GetAllDepthChildrenCount()3539  int32_t FrameNode::GetAllDepthChildrenCount()
3540  {
3541      int32_t result = 0;
3542      std::list<RefPtr<FrameNode>> children;
3543      children.emplace_back(Claim(this));
3544      while (!children.empty()) {
3545          auto& node = children.front();
3546          if (!node->IsInternal()) {
3547              result++;
3548              node->GenerateOneDepthVisibleFrame(children);
3549          }
3550          children.pop_front();
3551      }
3552      return result;
3553  }
3554  
OnAccessibilityEvent(AccessibilityEventType eventType,WindowsContentChangeTypes windowsContentChangeType) const3555  void FrameNode::OnAccessibilityEvent(
3556      AccessibilityEventType eventType, WindowsContentChangeTypes windowsContentChangeType) const
3557  {
3558      if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3559          AccessibilityEvent event;
3560          event.type = eventType;
3561          event.windowContentChangeTypes = windowsContentChangeType;
3562          event.nodeId = GetAccessibilityId();
3563          auto pipeline = GetContext();
3564          CHECK_NULL_VOID(pipeline);
3565          pipeline->SendEventToAccessibility(event);
3566      }
3567  }
3568  
OnAccessibilityEventForVirtualNode(AccessibilityEventType eventType,int64_t accessibilityId)3569  void FrameNode::OnAccessibilityEventForVirtualNode(AccessibilityEventType eventType, int64_t accessibilityId)
3570  {
3571      if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3572          AccessibilityEvent event;
3573          event.type = eventType;
3574          event.windowContentChangeTypes = WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID;
3575          event.nodeId = accessibilityId;
3576          auto pipeline = GetContext();
3577          CHECK_NULL_VOID(pipeline);
3578          pipeline->SendEventToAccessibility(event);
3579      }
3580  }
3581  
OnAccessibilityEvent(AccessibilityEventType eventType,std::string beforeText,std::string latestContent)3582  void FrameNode::OnAccessibilityEvent(
3583      AccessibilityEventType eventType, std::string beforeText, std::string latestContent)
3584  {
3585      if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3586          AccessibilityEvent event;
3587          event.type = eventType;
3588          event.nodeId = GetAccessibilityId();
3589          event.beforeText = beforeText;
3590          event.latestContent = latestContent;
3591          auto pipeline = GetContext();
3592          CHECK_NULL_VOID(pipeline);
3593          pipeline->SendEventToAccessibilityWithNode(event, Claim(this));
3594      }
3595  }
3596  
OnAccessibilityEvent(AccessibilityEventType eventType,int64_t stackNodeId,WindowsContentChangeTypes windowsContentChangeType)3597  void FrameNode::OnAccessibilityEvent(
3598      AccessibilityEventType eventType, int64_t stackNodeId, WindowsContentChangeTypes windowsContentChangeType)
3599  {
3600      if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3601          AccessibilityEvent event;
3602          event.type = eventType;
3603          event.windowContentChangeTypes = windowsContentChangeType;
3604          event.nodeId = GetAccessibilityId();
3605          event.stackNodeId = stackNodeId;
3606          auto pipeline = GetContext();
3607          CHECK_NULL_VOID(pipeline);
3608          pipeline->SendEventToAccessibility(event);
3609      }
3610  }
3611  
OnAccessibilityEvent(AccessibilityEventType eventType,std::string textAnnouncedForAccessibility)3612  void FrameNode::OnAccessibilityEvent(
3613      AccessibilityEventType eventType, std::string textAnnouncedForAccessibility)
3614  {
3615      if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3616          if (eventType != AccessibilityEventType::ANNOUNCE_FOR_ACCESSIBILITY) {
3617              return;
3618          }
3619          AccessibilityEvent event;
3620          event.type = eventType;
3621          event.nodeId = GetAccessibilityId();
3622          event.textAnnouncedForAccessibility = textAnnouncedForAccessibility;
3623          auto pipeline = GetContext();
3624          CHECK_NULL_VOID(pipeline);
3625          pipeline->SendEventToAccessibilityWithNode(event, Claim(this));
3626      }
3627  }
3628  
OnRecycle()3629  void FrameNode::OnRecycle()
3630  {
3631      for (const auto& destroyCallback : destroyCallbacks_) {
3632          destroyCallback();
3633      }
3634      for (const auto& destroyCallback : destroyCallbacksMap_) {
3635          if (destroyCallback.second) {
3636              destroyCallback.second();
3637          }
3638      }
3639      layoutProperty_->ResetGeometryTransition();
3640      pattern_->OnRecycle();
3641      UINode::OnRecycle();
3642  }
3643  
OnReuse()3644  void FrameNode::OnReuse()
3645  {
3646      pattern_->OnReuse();
3647      UINode::OnReuse();
3648      if (SystemProperties::GetDeveloperModeOn()) {
3649          PaintDebugBoundary(SystemProperties::GetDebugBoundaryEnabled());
3650      }
3651  }
3652  
MarkRemoving()3653  bool FrameNode::MarkRemoving()
3654  {
3655      bool pendingRemove = false;
3656      if (!layoutProperty_ || !geometryNode_) {
3657          return pendingRemove;
3658      }
3659  
3660      isRemoving_ = true;
3661  
3662      const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
3663      if (geometryTransition != nullptr) {
3664          geometryTransition->Build(WeakClaim(this), false);
3665          pendingRemove = true;
3666      }
3667  
3668      const auto children = GetChildren();
3669      for (const auto& child : children) {
3670          pendingRemove = child->MarkRemoving() || pendingRemove;
3671      }
3672      return pendingRemove;
3673  }
3674  
AddHotZoneRect(const DimensionRect & hotZoneRect) const3675  void FrameNode::AddHotZoneRect(const DimensionRect& hotZoneRect) const
3676  {
3677      auto gestureHub = GetOrCreateGestureEventHub();
3678      gestureHub->AddResponseRect(hotZoneRect);
3679  }
3680  
RemoveLastHotZoneRect() const3681  void FrameNode::RemoveLastHotZoneRect() const
3682  {
3683      auto gestureHub = GetOrCreateGestureEventHub();
3684      gestureHub->RemoveLastResponseRect();
3685  }
3686  
OnRemoveFromParent(bool allowTransition)3687  bool FrameNode::OnRemoveFromParent(bool allowTransition)
3688  {
3689      // kick out transition animation if needed, wont re-entry if already detached.
3690      DetachFromMainTree(!allowTransition);
3691      auto context = GetRenderContext();
3692      CHECK_NULL_RETURN(context, false);
3693      if (!allowTransition || RemoveImmediately()) {
3694          // directly remove, reset parent and depth
3695          ResetParent();
3696          return true;
3697      }
3698      // delayed remove, will move self into disappearing children
3699      return false;
3700  }
3701  
FindChildByPosition(float x,float y)3702  RefPtr<FrameNode> FrameNode::FindChildByPosition(float x, float y)
3703  {
3704      std::map<int32_t, RefPtr<FrameNode>> hitFrameNodes;
3705      std::list<RefPtr<FrameNode>> children;
3706      GenerateOneDepthAllFrame(children);
3707      for (const auto& child : children) {
3708          if (!child->IsActive()) {
3709              continue;
3710          }
3711          auto geometryNode = child->GetGeometryNode();
3712          if (!geometryNode) {
3713              continue;
3714          }
3715  
3716          auto globalFrameRect = geometryNode->GetFrameRect();
3717          globalFrameRect.SetOffset(child->GetOffsetRelativeToWindow());
3718  
3719          if (globalFrameRect.IsInRegion(PointF(x, y))) {
3720              hitFrameNodes.insert(std::make_pair(child->GetDepth(), child));
3721          }
3722      }
3723  
3724      if (hitFrameNodes.empty()) {
3725          return nullptr;
3726      }
3727  
3728      return hitFrameNodes.rbegin()->second;
3729  }
3730  
FindChildByPositionWithoutChildTransform(float x,float y)3731  RefPtr<FrameNode> FrameNode::FindChildByPositionWithoutChildTransform(float x, float y)
3732  {
3733      std::map<int32_t, RefPtr<FrameNode>> hitFrameNodes;
3734      std::list<RefPtr<FrameNode>> children;
3735      GenerateOneDepthAllFrame(children);
3736      auto parentOffset = GetPositionToWindowWithTransform();
3737      for (const auto& child : children) {
3738          if (!child->IsActive()) {
3739              continue;
3740          }
3741          auto geometryNode = child->GetGeometryNode();
3742          if (!geometryNode) {
3743              continue;
3744          }
3745  
3746          auto globalFrameRect = geometryNode->GetFrameRect();
3747          auto childOffset = child->GetGeometryNode()->GetFrameOffset();
3748          childOffset += parentOffset;
3749          globalFrameRect.SetOffset(childOffset);
3750  
3751          if (globalFrameRect.IsInRegion(PointF(x, y))) {
3752              hitFrameNodes.insert(std::make_pair(child->GetDepth(), child));
3753          }
3754      }
3755  
3756      if (hitFrameNodes.empty()) {
3757          return nullptr;
3758      }
3759  
3760      return hitFrameNodes.rbegin()->second;
3761  }
3762  
GetAnimatablePropertyFloat(const std::string & propertyName) const3763  RefPtr<NodeAnimatablePropertyBase> FrameNode::GetAnimatablePropertyFloat(const std::string& propertyName) const
3764  {
3765      auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3766      if (iter == nodeAnimatablePropertyMap_.end()) {
3767          return nullptr;
3768      }
3769      return iter->second;
3770  }
3771  
FindChildByName(const RefPtr<FrameNode> & parentNode,const std::string & nodeName)3772  RefPtr<FrameNode> FrameNode::FindChildByName(const RefPtr<FrameNode>& parentNode, const std::string& nodeName)
3773  {
3774      CHECK_NULL_RETURN(parentNode, nullptr);
3775      const auto& children = parentNode->GetChildren();
3776      for (const auto& child : children) {
3777          auto childFrameNode = AceType::DynamicCast<FrameNode>(child);
3778          if (childFrameNode && childFrameNode->GetInspectorId().value_or("") == nodeName) {
3779              return childFrameNode;
3780          }
3781          auto childFindResult = FindChildByName(childFrameNode, nodeName);
3782          if (childFindResult) {
3783              return childFindResult;
3784          }
3785      }
3786      return nullptr;
3787  }
3788  
CreateAnimatablePropertyFloat(const std::string & propertyName,float value,const std::function<void (float)> & onCallbackEvent,const PropertyUnit & propertyType)3789  void FrameNode::CreateAnimatablePropertyFloat(const std::string& propertyName, float value,
3790      const std::function<void(float)>& onCallbackEvent, const PropertyUnit& propertyType)
3791  {
3792      auto context = GetRenderContext();
3793      CHECK_NULL_VOID(context);
3794      auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3795      if (iter != nodeAnimatablePropertyMap_.end()) {
3796          return;
3797      }
3798      auto property = AceType::MakeRefPtr<NodeAnimatablePropertyFloat>(value, std::move(onCallbackEvent));
3799      context->AttachNodeAnimatableProperty(property);
3800      if (propertyType == PropertyUnit::PIXEL_POSITION) {
3801          property->SetPropertyUnit(propertyType);
3802      }
3803      nodeAnimatablePropertyMap_.emplace(propertyName, property);
3804  }
3805  
DeleteAnimatablePropertyFloat(const std::string & propertyName)3806  void FrameNode::DeleteAnimatablePropertyFloat(const std::string& propertyName)
3807  {
3808      auto context = GetRenderContext();
3809      CHECK_NULL_VOID(context);
3810      RefPtr<NodeAnimatablePropertyBase> propertyRef = GetAnimatablePropertyFloat(propertyName);
3811      if (propertyRef) {
3812          context->DetachNodeAnimatableProperty(propertyRef);
3813          nodeAnimatablePropertyMap_.erase(propertyName);
3814      }
3815  }
3816  
UpdateAnimatablePropertyFloat(const std::string & propertyName,float value)3817  void FrameNode::UpdateAnimatablePropertyFloat(const std::string& propertyName, float value)
3818  {
3819      auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3820      if (iter == nodeAnimatablePropertyMap_.end()) {
3821          return;
3822      }
3823      auto property = AceType::DynamicCast<NodeAnimatablePropertyFloat>(iter->second);
3824      CHECK_NULL_VOID(property);
3825      property->Set(value);
3826      if (AnimationUtils::IsImplicitAnimationOpen()) {
3827          AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_START_ANIMATION);
3828      }
3829  }
3830  
CreateAnimatableArithmeticProperty(const std::string & propertyName,RefPtr<CustomAnimatableArithmetic> & value,std::function<void (const RefPtr<CustomAnimatableArithmetic> &)> & onCallbackEvent)3831  void FrameNode::CreateAnimatableArithmeticProperty(const std::string& propertyName,
3832      RefPtr<CustomAnimatableArithmetic>& value,
3833      std::function<void(const RefPtr<CustomAnimatableArithmetic>&)>& onCallbackEvent)
3834  {
3835      auto context = GetRenderContext();
3836      CHECK_NULL_VOID(context);
3837      auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3838      if (iter != nodeAnimatablePropertyMap_.end()) {
3839          return;
3840      }
3841      auto property = AceType::MakeRefPtr<NodeAnimatableArithmeticProperty>(value, std::move(onCallbackEvent));
3842      context->AttachNodeAnimatableProperty(property);
3843      nodeAnimatablePropertyMap_.emplace(propertyName, property);
3844  }
3845  
UpdateAnimatableArithmeticProperty(const std::string & propertyName,RefPtr<CustomAnimatableArithmetic> & value)3846  void FrameNode::UpdateAnimatableArithmeticProperty(
3847      const std::string& propertyName, RefPtr<CustomAnimatableArithmetic>& value)
3848  {
3849      auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3850      if (iter == nodeAnimatablePropertyMap_.end()) {
3851          return;
3852      }
3853      auto property = AceType::DynamicCast<NodeAnimatableArithmeticProperty>(iter->second);
3854      CHECK_NULL_VOID(property);
3855      property->Set(value);
3856  }
3857  
ProvideRestoreInfo()3858  std::string FrameNode::ProvideRestoreInfo()
3859  {
3860      return pattern_->ProvideRestoreInfo();
3861  }
3862  
RemoveImmediately() const3863  bool FrameNode::RemoveImmediately() const
3864  {
3865      auto context = GetRenderContext();
3866      CHECK_NULL_RETURN(context, true);
3867      // has transition out animation, need to wait for animation end
3868      return !context->HasTransitionOutAnimation();
3869  }
3870  
GetNodesById(const std::unordered_set<int32_t> & set)3871  std::vector<RefPtr<FrameNode>> FrameNode::GetNodesById(const std::unordered_set<int32_t>& set)
3872  {
3873      std::vector<RefPtr<FrameNode>> nodes;
3874      for (auto nodeId : set) {
3875          auto uiNode = ElementRegister::GetInstance()->GetUINodeById(nodeId);
3876          if (!uiNode) {
3877              continue;
3878          }
3879          auto frameNode = DynamicCast<FrameNode>(uiNode);
3880          if (frameNode) {
3881              nodes.emplace_back(frameNode);
3882          }
3883      }
3884      return nodes;
3885  }
3886  
GetNodesPtrById(const std::unordered_set<int32_t> & set)3887  std::vector<FrameNode*> FrameNode::GetNodesPtrById(const std::unordered_set<int32_t>& set)
3888  {
3889      std::vector<FrameNode*> nodes;
3890      for (auto nodeId : set) {
3891          NG::FrameNode* frameNode = ElementRegister::GetInstance()->GetFrameNodePtrById(nodeId);
3892          if (!frameNode) {
3893              continue;
3894          }
3895          nodes.emplace_back(frameNode);
3896      }
3897      return nodes;
3898  }
3899  
GetPreviewScaleVal() const3900  double FrameNode::GetPreviewScaleVal() const
3901  {
3902      double scale = 1.0;
3903      auto maxWidth = DragDropManager::GetMaxWidthBaseOnGridSystem(GetContextRefPtr());
3904      auto geometryNode = GetGeometryNode();
3905      CHECK_NULL_RETURN(geometryNode, scale);
3906      auto width = geometryNode->GetFrameRect().Width();
3907      if (GetTag() != V2::WEB_ETS_TAG && width != 0 && width > maxWidth && previewOption_.isScaleEnabled) {
3908          scale = maxWidth / width;
3909      }
3910      return scale;
3911  }
3912  
IsPreviewNeedScale() const3913  bool FrameNode::IsPreviewNeedScale() const
3914  {
3915      return GetPreviewScaleVal() < 1.0f;
3916  }
3917  
GetNodeExpectedRate()3918  int32_t FrameNode::GetNodeExpectedRate()
3919  {
3920      if (sceneRateMap_.empty()) {
3921          return 0;
3922      }
3923      auto iter = std::max_element(
3924          sceneRateMap_.begin(), sceneRateMap_.end(), [](auto a, auto b) { return a.second < b.second; });
3925      return iter->second;
3926  }
3927  
AddFRCSceneInfo(const std::string & scene,float speed,SceneStatus status)3928  void FrameNode::AddFRCSceneInfo(const std::string& scene, float speed, SceneStatus status)
3929  {
3930      if (SystemProperties::GetDebugEnabled()) {
3931          const std::string sceneStatusStrs[] = { "START", "RUNNING", "END" };
3932          LOGD("%{public}s  AddFRCSceneInfo scene:%{public}s   speed:%{public}f  status:%{public}s", GetTag().c_str(),
3933              scene.c_str(), std::abs(speed), sceneStatusStrs[static_cast<int32_t>(status)].c_str());
3934      }
3935  
3936      auto renderContext = GetRenderContext();
3937      CHECK_NULL_VOID(renderContext);
3938      auto pipelineContext = GetContext();
3939      CHECK_NULL_VOID(pipelineContext);
3940      auto frameRateManager = pipelineContext->GetFrameRateManager();
3941      CHECK_NULL_VOID(frameRateManager);
3942  
3943      auto expectedRate = renderContext->CalcExpectedFrameRate(scene, std::abs(speed));
3944      auto nodeId = GetId();
3945      auto iter = sceneRateMap_.find(scene);
3946      switch (status) {
3947          case SceneStatus::START: {
3948              if (iter == sceneRateMap_.end()) {
3949                  if (sceneRateMap_.empty()) {
3950                      frameRateManager->AddNodeRate(nodeId);
3951                  }
3952                  sceneRateMap_.emplace(scene, expectedRate);
3953                  frameRateManager->UpdateNodeRate(nodeId, GetNodeExpectedRate());
3954              }
3955              return;
3956          }
3957          case SceneStatus::RUNNING: {
3958              if (iter != sceneRateMap_.end() && iter->second != expectedRate) {
3959                  iter->second = expectedRate;
3960                  auto nodeExpectedRate = GetNodeExpectedRate();
3961                  frameRateManager->UpdateNodeRate(nodeId, nodeExpectedRate);
3962              }
3963              return;
3964          }
3965          case SceneStatus::END: {
3966              if (iter != sceneRateMap_.end()) {
3967                  sceneRateMap_.erase(iter);
3968                  if (sceneRateMap_.empty()) {
3969                      frameRateManager->RemoveNodeRate(nodeId);
3970                  } else {
3971                      auto nodeExpectedRate = GetNodeExpectedRate();
3972                      frameRateManager->UpdateNodeRate(nodeId, nodeExpectedRate);
3973                  }
3974              }
3975              return;
3976          }
3977          default:
3978              return;
3979      }
3980  }
3981  
GetPercentSensitive()3982  void FrameNode::GetPercentSensitive()
3983  {
3984      auto res = layoutProperty_->GetPercentSensitive();
3985      if (res.first) {
3986          if (layoutAlgorithm_) {
3987              layoutAlgorithm_->SetPercentWidth(true);
3988          }
3989      }
3990      if (res.second) {
3991          if (layoutAlgorithm_) {
3992              layoutAlgorithm_->SetPercentHeight(true);
3993          }
3994      }
3995  }
3996  
UpdatePercentSensitive()3997  void FrameNode::UpdatePercentSensitive()
3998  {
3999      bool percentHeight = layoutAlgorithm_ ? layoutAlgorithm_->GetPercentHeight() : true;
4000      bool percentWidth = layoutAlgorithm_ ? layoutAlgorithm_->GetPercentWidth() : true;
4001      auto res = layoutProperty_->UpdatePercentSensitive(percentHeight, percentWidth);
4002      if (res.first) {
4003          auto parent = GetAncestorNodeOfFrame();
4004          if (parent && parent->layoutAlgorithm_) {
4005              parent->layoutAlgorithm_->SetPercentWidth(true);
4006          }
4007      }
4008      if (res.second) {
4009          auto parent = GetAncestorNodeOfFrame();
4010          if (parent && parent->layoutAlgorithm_) {
4011              parent->layoutAlgorithm_->SetPercentHeight(true);
4012          }
4013      }
4014  }
4015  
4016  // This will call child and self measure process.
Measure(const std::optional<LayoutConstraintF> & parentConstraint)4017  void FrameNode::Measure(const std::optional<LayoutConstraintF>& parentConstraint)
4018  {
4019      ACE_LAYOUT_TRACE_BEGIN("Measure[%s][self:%d][parent:%d][key:%s]", GetTag().c_str(), GetId(),
4020          GetAncestorNodeOfFrame() ? GetAncestorNodeOfFrame()->GetId() : 0, GetInspectorIdValue("").c_str());
4021      ArkUIPerfMonitor::GetInstance().RecordLayoutNode();
4022      isLayoutComplete_ = false;
4023      if (!oldGeometryNode_) {
4024          oldGeometryNode_ = geometryNode_->Clone();
4025      }
4026      pattern_->BeforeCreateLayoutWrapper();
4027      GetLayoutAlgorithm(true);
4028  
4029      if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
4030          layoutAlgorithm_->SetSkipMeasure();
4031          layoutAlgorithm_->SetSkipLayout();
4032          geometryNode_->SetFrameSize(SizeF());
4033          geometryNode_->UpdateMargin(MarginPropertyF());
4034          isLayoutDirtyMarked_ = false;
4035          ACE_LAYOUT_TRACE_END()
4036          return;
4037      }
4038      if (!isActive_) {
4039          layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
4040      }
4041  
4042      if (layoutAlgorithm_->SkipMeasure()) {
4043          isLayoutDirtyMarked_ = false;
4044          ACE_LAYOUT_TRACE_END()
4045          return;
4046      }
4047  
4048      const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
4049      if (geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this))) {
4050          geometryTransition->WillLayout(Claim(this));
4051      }
4052      auto preConstraint = layoutProperty_->GetLayoutConstraint();
4053      auto contentConstraint = layoutProperty_->GetContentLayoutConstraint();
4054      layoutProperty_->BuildGridProperty(Claim(this));
4055  
4056      if (layoutProperty_->GetLayoutRect()) {
4057          layoutProperty_->UpdateLayoutConstraintWithLayoutRect();
4058      } else if (parentConstraint) {
4059          ApplyConstraint(*parentConstraint);
4060      } else {
4061          CreateRootConstraint();
4062      }
4063  
4064      layoutProperty_->UpdateContentConstraint();
4065      geometryNode_->UpdateMargin(layoutProperty_->CreateMargin());
4066      geometryNode_->UpdatePaddingWithBorder(layoutProperty_->CreatePaddingAndBorder());
4067  
4068      isConstraintNotChanged_ = layoutProperty_->ConstraintEqual(preConstraint, contentConstraint);
4069  
4070      isLayoutDirtyMarked_ = false;
4071  
4072      if (isConstraintNotChanged_) {
4073          if (!CheckNeedForceMeasureAndLayout()) {
4074              ACE_SCOPED_TRACE("SkipMeasure [%s][self:%d]", GetTag().c_str(), GetId());
4075              layoutAlgorithm_->SetSkipMeasure();
4076              ACE_LAYOUT_TRACE_END()
4077              return;
4078          }
4079      } else {
4080          contentConstraintChanges_.UpdateFlags(contentConstraint, layoutProperty_->GetContentLayoutConstraint());
4081          constraintChanges_.UpdateFlags(preConstraint, layoutProperty_->GetLayoutConstraint());
4082      }
4083  
4084      GetPercentSensitive();
4085  
4086      if (extensionHandler_ && !extensionHandler_->HasDrawModifier()) {
4087          auto extensionLayoutConstraint =
4088              ExtensionLayoutConstraint::Create(GetLayoutProperty()->GetLayoutConstraint().value());
4089          extensionHandler_->SetInnerMeasureImpl([this](const ExtensionLayoutConstraint&) {
4090              auto size = layoutAlgorithm_->MeasureContent(layoutProperty_->CreateContentConstraint(), this);
4091              if (size.has_value()) {
4092                  geometryNode_->SetContentSize(size.value());
4093              }
4094              layoutAlgorithm_->Measure(this);
4095          });
4096          extensionHandler_->Measure(extensionLayoutConstraint);
4097      } else {
4098          auto size = layoutAlgorithm_->MeasureContent(layoutProperty_->CreateContentConstraint(), this);
4099          if (size.has_value()) {
4100              geometryNode_->SetContentSize(size.value());
4101          }
4102          layoutAlgorithm_->Measure(this);
4103      }
4104  
4105      if (overlayNode_) {
4106          overlayNode_->Measure(layoutProperty_->CreateChildConstraint());
4107      }
4108      UpdatePercentSensitive();
4109      // check aspect radio.
4110      if (pattern_ && pattern_->IsNeedAdjustByAspectRatio() && !layoutProperty_->GetLayoutRect()) {
4111          const auto& magicItemProperty = layoutProperty_->GetMagicItemProperty();
4112          auto aspectRatio = magicItemProperty.GetAspectRatioValue();
4113          // Adjust by aspect ratio, firstly pick height based on width. It means that when width, height and
4114          // aspectRatio are all set, the height is not used.
4115          auto width = geometryNode_->GetFrameSize().Width();
4116          auto height = width / aspectRatio;
4117          geometryNode_->SetFrameSize(SizeF({ width, height }));
4118      }
4119  
4120      layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
4121      ACE_LAYOUT_TRACE_END()
4122  }
4123  
4124  // Called to perform layout children.
Layout()4125  void FrameNode::Layout()
4126  {
4127      ACE_LAYOUT_TRACE_BEGIN("Layout[%s][self:%d][parent:%d][key:%s]", GetTag().c_str(), GetId(),
4128          GetAncestorNodeOfFrame() ? GetAncestorNodeOfFrame()->GetId() : 0, GetInspectorIdValue("").c_str());
4129      if (layoutProperty_->GetLayoutRect()) {
4130          GetGeometryNode()->SetFrameOffset(layoutProperty_->GetLayoutRect().value().GetOffset());
4131      }
4132      int64_t time = GetSysTimestamp();
4133      OffsetNodeToSafeArea();
4134      const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
4135      if (geometryTransition != nullptr) {
4136          if (geometryTransition->IsNodeInAndActive(Claim(this))) {
4137              if (IsRootMeasureNode()) {
4138                  UINode::SetGeometryTransitionInRecursive(true);
4139              } else {
4140                  SetSkipSyncGeometryNode();
4141              }
4142          }
4143      }
4144      if (CheckNeedLayout(layoutProperty_->GetPropertyChangeFlag())) {
4145          if (!layoutProperty_->GetLayoutConstraint()) {
4146              const auto& parentLayoutConstraint = geometryNode_->GetParentLayoutConstraint();
4147              if (layoutProperty_->GetLayoutRect()) {
4148                  layoutProperty_->UpdateLayoutConstraintWithLayoutRect();
4149              } else if (parentLayoutConstraint) {
4150                  layoutProperty_->UpdateLayoutConstraint(parentLayoutConstraint.value());
4151              } else {
4152                  LayoutConstraintF layoutConstraint;
4153                  layoutConstraint.percentReference.SetWidth(PipelineContext::GetCurrentRootWidth());
4154                  layoutConstraint.percentReference.SetHeight(PipelineContext::GetCurrentRootHeight());
4155                  layoutProperty_->UpdateLayoutConstraint(layoutConstraint);
4156              }
4157              layoutProperty_->UpdateContentConstraint();
4158          }
4159  
4160          if (extensionHandler_ && !extensionHandler_->HasDrawModifier()) {
4161              extensionHandler_->SetInnerLayoutImpl(
4162                  [this](int32_t, int32_t, int32_t, int32_t) { GetLayoutAlgorithm()->Layout(this); });
4163              const auto& rect = geometryNode_->GetFrameRect();
4164              extensionHandler_->Layout(rect.Width(), rect.Height(), rect.GetX(), rect.GetY());
4165          } else {
4166              GetLayoutAlgorithm()->Layout(this);
4167          }
4168  
4169          if (overlayNode_) {
4170              LayoutOverlay();
4171          }
4172          time = GetSysTimestamp() - time;
4173          AddNodeFlexLayouts();
4174          AddNodeLayoutTime(time);
4175      } else {
4176          GetLayoutAlgorithm()->SetSkipLayout();
4177      }
4178  
4179      auto pipeline = GetContext();
4180      CHECK_NULL_VOID_LAYOUT_TRACE_END(pipeline);
4181      auto stageManager = pipeline->GetStageManager();
4182      CHECK_NULL_VOID(stageManager);
4183      bool isFocusOnPage = stageManager->CheckPageFocus();
4184      bool needSyncRsNode = false;
4185      DirtySwapConfig config;
4186      bool willSyncGeoProperties = OnLayoutFinish(needSyncRsNode, config);
4187      needSyncRsNode |= AvoidKeyboard(isFocusOnPage);
4188      if (GetIsGeometryTransitionIn()) {
4189          renderContext_->SetFrameWithoutAnimation(renderContext_->GetPaintRectWithoutTransform());
4190          SetIsGeometryTransitionIn(false);
4191      }
4192      // skip wrapping task if node will not sync
4193      CHECK_NULL_VOID_LAYOUT_TRACE_END(willSyncGeoProperties);
4194      auto task = [weak = WeakClaim(this), needSync = needSyncRsNode, dirtyConfig = config]() {
4195          auto frameNode = weak.Upgrade();
4196          CHECK_NULL_VOID(frameNode);
4197          frameNode->SyncGeometryNode(needSync, dirtyConfig);
4198      };
4199      pipeline->AddSyncGeometryNodeTask(task);
4200      if (SelfOrParentExpansive()) {
4201          auto pipeline = GetContext();
4202          CHECK_NULL_VOID_LAYOUT_TRACE_END(pipeline);
4203          auto safeAreaManager = pipeline->GetSafeAreaManager();
4204          CHECK_NULL_VOID_LAYOUT_TRACE_END(safeAreaManager);
4205          safeAreaManager->AddNeedExpandNode(GetHostNode());
4206      }
4207      // if a node has geo transition but not the root node, add task only but not flush
4208      // or add to expand list, self node will be added to expand list in next layout
4209      if (geometryTransition != nullptr && !IsRootMeasureNode()) {
4210          ACE_LAYOUT_TRACE_END()
4211          return;
4212      }
4213      if (geometryTransition != nullptr) {
4214          pipeline->FlushSyncGeometryNodeTasks();
4215      }
4216      ACE_LAYOUT_TRACE_END()
4217  }
4218  
SelfExpansive()4219  bool FrameNode::SelfExpansive()
4220  {
4221      auto&& opts = GetLayoutProperty()->GetSafeAreaExpandOpts();
4222      return opts && (opts->Expansive() || opts->switchToNone);
4223  }
4224  
SelfExpansiveToKeyboard()4225  bool FrameNode::SelfExpansiveToKeyboard()
4226  {
4227      auto&& opts = GetLayoutProperty()->GetSafeAreaExpandOpts();
4228      return opts && opts->ExpansiveToKeyboard();
4229  }
4230  
ParentExpansive()4231  bool FrameNode::ParentExpansive()
4232  {
4233      auto parent = GetAncestorNodeOfFrame();
4234      CHECK_NULL_RETURN(parent, false);
4235      auto parentLayoutProperty = parent->GetLayoutProperty();
4236      CHECK_NULL_RETURN(parentLayoutProperty, false);
4237      auto&& parentOpts = parentLayoutProperty->GetSafeAreaExpandOpts();
4238      return parentOpts && parentOpts->Expansive();
4239  }
4240  
ProcessSafeAreaPadding()4241  void FrameNode::ProcessSafeAreaPadding()
4242  {
4243      pattern_->ProcessSafeAreaPadding();
4244  }
4245  
UpdateFocusState()4246  void FrameNode::UpdateFocusState()
4247  {
4248      auto focusHub = GetFocusHub();
4249      if (focusHub && focusHub->IsCurrentFocus()) {
4250          focusHub->ClearFocusState();
4251          focusHub->PaintFocusState();
4252      }
4253  }
4254  
SelfOrParentExpansive()4255  bool FrameNode::SelfOrParentExpansive()
4256  {
4257      return SelfExpansive() || ParentExpansive();
4258  }
4259  
ProcessAccessibilityVirtualNode()4260  void FrameNode::ProcessAccessibilityVirtualNode()
4261  {
4262      if (!hasAccessibilityVirtualNode_) {
4263          return;
4264      }
4265      auto accessibilityProperty = GetAccessibilityProperty<AccessibilityProperty>();
4266      auto virtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
4267      auto virtualFrameNode = AceType::DynamicCast<NG::FrameNode>(virtualNode);
4268      if (virtualFrameNode) {
4269          auto constraint = GetLayoutConstraint();
4270          virtualFrameNode->ApplyConstraint(constraint);
4271          ProcessOffscreenNode(virtualFrameNode);
4272      }
4273  }
4274  
UpdateAccessibilityNodeRect()4275  void FrameNode::UpdateAccessibilityNodeRect()
4276  {
4277      auto accessibilityProperty = GetAccessibilityProperty<AccessibilityProperty>();
4278      CHECK_NULL_VOID(accessibilityProperty);
4279      auto isFocus = accessibilityProperty->GetAccessibilityFocusState();
4280      if (isFocus && !IsAccessibilityVirtualNode()) {
4281          renderContext_->UpdateAccessibilityRoundRect();
4282      }
4283  }
4284  
OnLayoutFinish(bool & needSyncRsNode,DirtySwapConfig & config)4285  bool FrameNode::OnLayoutFinish(bool& needSyncRsNode, DirtySwapConfig& config)
4286  {
4287      auto context = GetContext();
4288      if (isLayoutNode_ && context) {
4289          context->AddLayoutNode(Claim(this));
4290      }
4291      isLayoutComplete_ = true;
4292      const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
4293      bool hasTransition = geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this));
4294      if (!isActive_ && !hasTransition) {
4295          layoutAlgorithm_.Reset();
4296          return false;
4297      }
4298      if (needSkipSyncGeometryNode_ && (!geometryTransition || !geometryTransition->IsNodeInAndActive(Claim(this)))) {
4299          layoutAlgorithm_.Reset();
4300          return false;
4301      }
4302      // update layout size.
4303      bool frameSizeChange = true;
4304      bool frameOffsetChange = true;
4305      bool contentSizeChange = true;
4306      bool contentOffsetChange = true;
4307      if (oldGeometryNode_) {
4308          frameSizeChange = geometryNode_->GetFrameSize() != oldGeometryNode_->GetFrameSize();
4309          frameOffsetChange = geometryNode_->GetFrameOffset() != oldGeometryNode_->GetFrameOffset();
4310          contentSizeChange = geometryNode_->GetContentSize() != oldGeometryNode_->GetContentSize();
4311          contentOffsetChange = geometryNode_->GetContentOffset() != oldGeometryNode_->GetContentOffset();
4312          oldGeometryNode_.Reset();
4313      }
4314  
4315      // clean layout flag.
4316      layoutProperty_->CleanDirty();
4317      needSyncRsNode = frameSizeChange || frameOffsetChange ||
4318                       (pattern_->GetContextParam().has_value() && contentSizeChange) || HasPositionProp() ||
4319                       SelfOrParentExpansive();
4320      if (hasTransition) {
4321          geometryTransition->DidLayout(Claim(this));
4322          if (geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
4323              isLayoutDirtyMarked_ = true;
4324          }
4325          needSyncRsNode = false;
4326      }
4327      if (GetTag() != V2::PAGE_ETS_TAG) {
4328          renderContext_->SavePaintRect(true, layoutProperty_->GetPixelRound());
4329          if (needSyncRsNode) {
4330              renderContext_->SyncPartialRsProperties();
4331          }
4332      }
4333      config = { .frameSizeChange = frameSizeChange,
4334          .frameOffsetChange = frameOffsetChange,
4335          .contentSizeChange = contentSizeChange,
4336          .contentOffsetChange = contentOffsetChange };
4337      // check if need to paint content.
4338      auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(layoutAlgorithm_);
4339      CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
4340      config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure();
4341      config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
4342      if (!config.skipMeasure && !config.skipLayout && GetInspectorId()) {
4343          auto pipeline = PipelineContext::GetCurrentContext();
4344          CHECK_NULL_RETURN(pipeline, false);
4345          pipeline->OnLayoutCompleted(GetInspectorId()->c_str());
4346      }
4347      auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config);
4348      needRerender =
4349          needRerender || pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config.skipMeasure, config.skipLayout);
4350      if (needRerender || (extensionHandler_ && extensionHandler_->NeedRender()) ||
4351          CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
4352          MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
4353      }
4354      layoutAlgorithm_.Reset();
4355      UpdateAccessibilityNodeRect();
4356      ProcessAccessibilityVirtualNode();
4357      auto pipeline = GetContext();
4358      CHECK_NULL_RETURN(pipeline, false);
4359      pipeline->SendUpdateVirtualNodeFocusEvent();
4360      return true;
4361  }
4362  
SyncGeometryNode(bool needSyncRsNode,const DirtySwapConfig & config)4363  void FrameNode::SyncGeometryNode(bool needSyncRsNode, const DirtySwapConfig& config)
4364  {
4365      if (SystemProperties::GetSyncDebugTraceEnabled()) {
4366          ACE_LAYOUT_TRACE_BEGIN("SyncGeometryNode[%s][self:%d][parent:%d][key:%s]", GetTag().c_str(), GetId(),
4367              GetParent() ? GetParent()->GetId() : 0, GetInspectorIdValue("").c_str());
4368          ACE_LAYOUT_TRACE_END()
4369      }
4370  
4371      // update border.
4372      if (layoutProperty_->GetBorderWidthProperty()) {
4373          if (!renderContext_->HasBorderColor()) {
4374              BorderColorProperty borderColorProperty;
4375              borderColorProperty.SetColor(Color::BLACK);
4376              renderContext_->UpdateBorderColor(borderColorProperty);
4377          }
4378          if (!renderContext_->HasBorderStyle()) {
4379              BorderStyleProperty borderStyleProperty;
4380              borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
4381              renderContext_->UpdateBorderStyle(borderStyleProperty);
4382          }
4383          if (!renderContext_->HasDashGap()) {
4384              BorderWidthProperty dashGapProperty;
4385              dashGapProperty.SetBorderWidth(Dimension(-1));
4386              renderContext_->UpdateDashGap(dashGapProperty);
4387          }
4388          if (!renderContext_->HasDashWidth()) {
4389              BorderWidthProperty dashWidthProperty;
4390              dashWidthProperty.SetBorderWidth(Dimension(-1));
4391              renderContext_->UpdateDashWidth(dashWidthProperty);
4392          }
4393          if (layoutProperty_->GetLayoutConstraint().has_value()) {
4394              renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
4395                  ScaleProperty::CreateScaleProperty(),
4396                  layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
4397          } else {
4398              renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
4399                  ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
4400          }
4401      }
4402  
4403      pattern_->OnSyncGeometryNode(config);
4404      if (needSyncRsNode) {
4405          pattern_->BeforeSyncGeometryProperties(config);
4406          renderContext_->SyncGeometryProperties(RawPtr(geometryNode_), true, layoutProperty_->GetPixelRound());
4407          if (SystemProperties::GetSyncDebugTraceEnabled()) {
4408              ACE_LAYOUT_TRACE_BEGIN("TriggerOnSizeChangeNode:[%s][id:%d]", GetTag().c_str(), GetId());
4409              ACE_LAYOUT_TRACE_END()
4410          }
4411          TriggerOnSizeChangeCallback();
4412      }
4413  
4414      // update background
4415      if (builderFunc_) {
4416          auto builderNode = builderFunc_();
4417          auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
4418              AceType::MakeRefPtr<LinearLayoutPattern>(true));
4419          if (builderNode) {
4420              builderNode->MountToParent(columnNode);
4421          }
4422          SetBackgroundLayoutConstraint(columnNode);
4423          renderContext_->CreateBackgroundPixelMap(columnNode);
4424          builderFunc_ = nullptr;
4425          backgroundNode_ = columnNode;
4426      }
4427  
4428      // update focus state
4429      UpdateFocusState();
4430  
4431      // rebuild child render node.
4432      if (!isLayoutNode_) {
4433          RebuildRenderContextTree();
4434      }
4435  
4436      /* Adjust components' position which have been set grid properties */
4437      AdjustGridOffset();
4438  }
4439  
GetOrCreateChildByIndex(uint32_t index,bool addToRenderTree,bool isCache)4440  RefPtr<LayoutWrapper> FrameNode::GetOrCreateChildByIndex(uint32_t index, bool addToRenderTree, bool isCache)
4441  {
4442      auto child = frameProxy_->GetFrameNodeByIndex(index, true, isCache, addToRenderTree);
4443      if (child) {
4444          child->SetSkipSyncGeometryNode(SkipSyncGeometryNode());
4445          if (addToRenderTree) {
4446              child->SetActive(true);
4447          }
4448      }
4449      return child;
4450  }
4451  
GetChildByIndex(uint32_t index,bool isCache)4452  RefPtr<LayoutWrapper> FrameNode::GetChildByIndex(uint32_t index, bool isCache)
4453  {
4454      return frameProxy_->GetFrameNodeByIndex(index, false, isCache, false);
4455  }
4456  
GetFrameNodeChildByIndex(uint32_t index,bool isCache,bool isExpand)4457  FrameNode* FrameNode::GetFrameNodeChildByIndex(uint32_t index, bool isCache, bool isExpand)
4458  {
4459      auto frameNode = isExpand ? DynamicCast<FrameNode>(frameProxy_->GetFrameNodeByIndex(index, true, isCache, false))
4460                                : DynamicCast<FrameNode>(UINode::GetFrameChildByIndexWithoutExpanded(index));
4461      return RawPtr(frameNode);
4462  }
4463  
GetChildTrueIndex(const RefPtr<LayoutWrapper> & child) const4464  int32_t FrameNode::GetChildTrueIndex(const RefPtr<LayoutWrapper>& child) const
4465  {
4466      return frameProxy_->GetChildIndex(child);
4467  }
4468  
GetChildTrueTotalCount() const4469  uint32_t FrameNode::GetChildTrueTotalCount() const
4470  {
4471      return frameProxy_->GetTotalCount();
4472  }
4473  
GetAllChildrenWithBuild(bool addToRenderTree)4474  ChildrenListWithGuard FrameNode::GetAllChildrenWithBuild(bool addToRenderTree)
4475  {
4476      const auto& children = frameProxy_->GetAllFrameChildren();
4477      {
4478          auto guard = frameProxy_->GetGuard();
4479          for (const auto& child : children) {
4480              if (addToRenderTree) {
4481                  child->SetActive(true);
4482              }
4483              child->SetSkipSyncGeometryNode(SkipSyncGeometryNode());
4484          }
4485      }
4486      return children;
4487  }
4488  
RemoveAllChildInRenderTree()4489  void FrameNode::RemoveAllChildInRenderTree()
4490  {
4491      frameProxy_->RemoveAllChildInRenderTree();
4492  }
4493  
SetActiveChildRange(int32_t start,int32_t end,int32_t cacheStart,int32_t cacheEnd,bool showCached)4494  void FrameNode::SetActiveChildRange(int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd, bool showCached)
4495  {
4496      frameProxy_->SetActiveChildRange(start, end, cacheStart, cacheEnd, showCached);
4497  }
4498  
SetActiveChildRange(const std::optional<ActiveChildSets> & activeChildSets,const std::optional<ActiveChildRange> & activeChildRange)4499  void FrameNode::SetActiveChildRange(
4500      const std::optional<ActiveChildSets>& activeChildSets, const std::optional<ActiveChildRange>& activeChildRange)
4501  {
4502      frameProxy_->SetActiveChildRange(activeChildSets, activeChildRange);
4503  }
4504  
RecycleItemsByIndex(int32_t start,int32_t end)4505  void FrameNode::RecycleItemsByIndex(int32_t start, int32_t end)
4506  {
4507      frameProxy_->RecycleItemsByIndex(start, end);
4508  }
4509  
RemoveChildInRenderTree(uint32_t index)4510  void FrameNode::RemoveChildInRenderTree(uint32_t index)
4511  {
4512      frameProxy_->RemoveChildInRenderTree(index);
4513  }
4514  
SkipMeasureContent() const4515  bool FrameNode::SkipMeasureContent() const
4516  {
4517      return layoutAlgorithm_ && layoutAlgorithm_->SkipMeasure();
4518  }
4519  
CheckNeedForceMeasureAndLayout()4520  bool FrameNode::CheckNeedForceMeasureAndLayout()
4521  {
4522      PropertyChangeFlag flag = layoutProperty_->GetPropertyChangeFlag();
4523      return CheckNeedMeasure(flag) || CheckNeedLayout(flag);
4524  }
4525  
GetOffsetInScreen()4526  OffsetF FrameNode::GetOffsetInScreen()
4527  {
4528      auto frameOffset = GetPaintRectOffset();
4529      auto pipelineContext = PipelineContext::GetCurrentContext();
4530      CHECK_NULL_RETURN(pipelineContext, OffsetF(0.0f, 0.0f));
4531      auto window = pipelineContext->GetWindow();
4532      CHECK_NULL_RETURN(window, OffsetF(0.0f, 0.0f));
4533      auto windowOffset = window->GetCurrentWindowRect().GetOffset();
4534      frameOffset += OffsetT<float> { windowOffset.GetX(), windowOffset.GetY() };
4535      return frameOffset;
4536  }
4537  
GetOffsetInSubwindow(const OffsetF & subwindowOffset)4538  OffsetF FrameNode::GetOffsetInSubwindow(const OffsetF& subwindowOffset)
4539  {
4540      auto frameOffset = GetOffsetInScreen();
4541      frameOffset -= subwindowOffset;
4542      return frameOffset;
4543  }
4544  
GetPixelMap()4545  RefPtr<PixelMap> FrameNode::GetPixelMap()
4546  {
4547      auto gestureHub = GetOrCreateGestureEventHub();
4548      CHECK_NULL_RETURN(gestureHub, nullptr);
4549      RefPtr<PixelMap> pixelMap = gestureHub->GetPixelMap();
4550      // if gesture already have pixel map return directly
4551      if (pixelMap) {
4552          return pixelMap;
4553      }
4554      CHECK_NULL_RETURN(renderContext_, nullptr);
4555      pixelMap = renderContext_->GetThumbnailPixelMap();
4556      gestureHub->SetPixelMap(pixelMap);
4557      return pixelMap;
4558  }
4559  
GetBaselineDistance() const4560  float FrameNode::GetBaselineDistance() const
4561  {
4562      const auto& children = frameProxy_->GetAllFrameChildren();
4563      if (children.empty()) {
4564          return geometryNode_->GetBaselineDistance();
4565      }
4566      float distance = 0.0;
4567      {
4568          auto guard = frameProxy_->GetGuard();
4569          for (const auto& child : children) {
4570              float childBaseline = child->GetBaselineDistance();
4571              distance = NearZero(distance) ? childBaseline : std::min(distance, childBaseline);
4572          }
4573      }
4574      return distance;
4575  }
4576  
MarkNeedSyncRenderTree(bool needRebuild)4577  void FrameNode::MarkNeedSyncRenderTree(bool needRebuild)
4578  {
4579      if (needRebuild) {
4580          frameProxy_->ResetChildren(true);
4581      }
4582      needSyncRenderTree_ = true;
4583  }
4584  
GetFrameChildByIndex(uint32_t index,bool needBuild,bool isCache,bool addToRenderTree)4585  RefPtr<UINode> FrameNode::GetFrameChildByIndex(uint32_t index, bool needBuild, bool isCache, bool addToRenderTree)
4586  {
4587      if (index != 0) {
4588          return nullptr;
4589      }
4590      return Claim(this);
4591  }
4592  
GetFrameChildByIndexWithoutExpanded(uint32_t index)4593  RefPtr<UINode> FrameNode::GetFrameChildByIndexWithoutExpanded(uint32_t index)
4594  {
4595      return GetFrameChildByIndex(index, false);
4596  }
4597  
GetLayoutAlgorithm(bool needReset)4598  const RefPtr<LayoutAlgorithmWrapper>& FrameNode::GetLayoutAlgorithm(bool needReset)
4599  {
4600      if ((!layoutAlgorithm_ || (needReset && layoutAlgorithm_->IsExpire())) && pattern_) {
4601          layoutAlgorithm_ = MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm());
4602      }
4603      if (needReset) {
4604          layoutAlgorithm_->SetNeedMeasure();
4605      }
4606      return layoutAlgorithm_;
4607  }
4608  
SetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)4609  void FrameNode::SetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
4610  {
4611      frameProxy_->SetCacheCount(cacheCount, itemConstraint);
4612  }
4613  
LayoutOverlay()4614  void FrameNode::LayoutOverlay()
4615  {
4616      auto size = geometryNode_->GetFrameSize();
4617      auto align = Alignment::TOP_LEFT;
4618      Dimension offsetX, offsetY;
4619      auto childLayoutProperty = overlayNode_->GetLayoutProperty();
4620      childLayoutProperty->GetOverlayOffset(offsetX, offsetY);
4621      auto offset = OffsetF(offsetX.ConvertToPx(), offsetY.ConvertToPx());
4622      if (childLayoutProperty->GetPositionProperty()) {
4623          align = childLayoutProperty->GetPositionProperty()->GetAlignment().value_or(align);
4624      }
4625  
4626      auto childSize = overlayNode_->GetGeometryNode()->GetMarginFrameSize();
4627      auto translate = Alignment::GetAlignPosition(size, childSize, align) + offset;
4628      overlayNode_->GetGeometryNode()->SetMarginFrameOffset(translate);
4629      overlayNode_->Layout();
4630  }
4631  
DoRemoveChildInRenderTree(uint32_t index,bool isAll)4632  void FrameNode::DoRemoveChildInRenderTree(uint32_t index, bool isAll)
4633  {
4634      isActive_ = false;
4635      SetActive(false);
4636  }
4637  
DoSetActiveChildRange(int32_t start,int32_t end,int32_t cacheStart,int32_t cacheEnd,bool showCache)4638  void FrameNode::DoSetActiveChildRange(int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd, bool showCache)
4639  {
4640      if (showCache) {
4641          start -= cacheStart;
4642          end += cacheEnd;
4643      }
4644      if (start <= end) {
4645          if (start > 0 || end < 0) {
4646              SetActive(false);
4647              SetJSViewActive(false);
4648          } else {
4649              SetActive(true);
4650              SetJSViewActive(true);
4651          }
4652      } else {
4653          if (end < 0 && start > 0) {
4654              SetActive(false);
4655              SetJSViewActive(false);
4656          } else {
4657              SetActive(true);
4658              SetJSViewActive(true);
4659          }
4660      }
4661  }
4662  
OnInspectorIdUpdate(const std::string & id)4663  void FrameNode::OnInspectorIdUpdate(const std::string& id)
4664  {
4665      renderContext_->UpdateNodeName(id);
4666      ElementRegister::GetInstance()->AddFrameNodeByInspectorId(id, AceType::WeakClaim(this));
4667      auto parent = GetAncestorNodeOfFrame();
4668      if (parent && parent->GetTag() == V2::RELATIVE_CONTAINER_ETS_TAG) {
4669          parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
4670      }
4671      if (Recorder::EventRecorder::Get().IsExposureRecordEnable()) {
4672          if (exposureProcessor_) {
4673              return;
4674          }
4675          auto* context = GetContext();
4676          CHECK_NULL_VOID(context);
4677          context->AddAfterRenderTask([weak = WeakClaim(this), inspectorId = id]() {
4678              auto host = weak.Upgrade();
4679              CHECK_NULL_VOID(host);
4680              auto pageUrl = Recorder::GetPageUrlByNode(host);
4681              host->exposureProcessor_ = MakeRefPtr<Recorder::ExposureProcessor>(pageUrl, inspectorId);
4682              if (!host->exposureProcessor_->IsNeedRecord()) {
4683                  return;
4684              }
4685              host->RecordExposureInner();
4686          });
4687      }
4688  }
4689  
SetExposureProcessor(const RefPtr<Recorder::ExposureProcessor> & processor)4690  void FrameNode::SetExposureProcessor(const RefPtr<Recorder::ExposureProcessor>& processor)
4691  {
4692      if (exposureProcessor_ && exposureProcessor_->isListening()) {
4693          return;
4694      } else {
4695          exposureProcessor_ = MakeRefPtr<Recorder::ExposureProcessor>(processor);
4696          exposureProcessor_->SetContainerId(processor->GetContainerId());
4697      }
4698      exposureProcessor_->OnVisibleChange(true, "");
4699      RecordExposureInner();
4700  }
4701  
RecordExposureInner()4702  void FrameNode::RecordExposureInner()
4703  {
4704      auto pipeline = GetContext();
4705      if (!pipeline) {
4706          auto piplineRef = PipelineContext::GetContextByContainerId(exposureProcessor_->GetContainerId());
4707          if (!piplineRef) {
4708              pipeline = piplineRef.GetRawPtr();
4709          }
4710      }
4711      CHECK_NULL_VOID(pipeline);
4712      auto callback = [weak = WeakClaim(RawPtr(exposureProcessor_)), weakNode = WeakClaim(this)](
4713                          bool visible, double ratio) {
4714          auto processor = weak.Upgrade();
4715          CHECK_NULL_VOID(processor);
4716          if (!visible) {
4717              auto host = weakNode.Upgrade();
4718              auto param = host ? host->GetAutoEventParamValue("") : "";
4719              processor->OnVisibleChange(false, param);
4720          } else {
4721              processor->OnVisibleChange(visible);
4722          }
4723      };
4724      std::vector<double> ratios = { exposureProcessor_->GetRatio() };
4725      pipeline->AddVisibleAreaChangeNode(Claim(this), ratios, callback, false);
4726      exposureProcessor_->SetListenState(true);
4727  }
4728  
AddFrameNodeSnapshot(bool isHit,int32_t parentId,std::vector<RectF> responseRegionList,EventTreeType type)4729  void FrameNode::AddFrameNodeSnapshot(
4730      bool isHit, int32_t parentId, std::vector<RectF> responseRegionList, EventTreeType type)
4731  {
4732      auto context = PipelineContext::GetCurrentContext();
4733      CHECK_NULL_VOID(context);
4734      auto eventMgr = context->GetEventManager();
4735      CHECK_NULL_VOID(eventMgr);
4736  
4737      FrameNodeSnapshot info = { .nodeId = GetId(),
4738          .parentNodeId = parentId,
4739          .tag = GetTag(),
4740          .comId = propInspectorId_.value_or(""),
4741          .monopolizeEvents = GetMonopolizeEvents(),
4742          .isHit = isHit,
4743          .hitTestMode = static_cast<int32_t>(GetHitTestMode()),
4744          .responseRegionList = responseRegionList };
4745      eventMgr->GetEventTreeRecord(type).AddFrameNodeSnapshot(std::move(info));
4746  }
4747  
GetUiExtensionId()4748  int32_t FrameNode::GetUiExtensionId()
4749  {
4750      if (pattern_) {
4751          return pattern_->GetUiExtensionId();
4752      }
4753      return -1;
4754  }
4755  
WrapExtensionAbilityId(int64_t extensionOffset,int64_t abilityId)4756  int64_t FrameNode::WrapExtensionAbilityId(int64_t extensionOffset, int64_t abilityId)
4757  {
4758      if (pattern_) {
4759          return pattern_->WrapExtensionAbilityId(extensionOffset, abilityId);
4760      }
4761      return -1;
4762  }
4763  
SearchExtensionElementInfoByAccessibilityIdNG(int64_t elementId,int32_t mode,int64_t offset,std::list<Accessibility::AccessibilityElementInfo> & output)4764  void FrameNode::SearchExtensionElementInfoByAccessibilityIdNG(
4765      int64_t elementId, int32_t mode, int64_t offset, std::list<Accessibility::AccessibilityElementInfo>& output)
4766  {
4767      if (pattern_) {
4768          pattern_->SearchExtensionElementInfoByAccessibilityId(elementId, mode, offset, output);
4769      }
4770  }
4771  
SearchElementInfosByTextNG(int64_t elementId,const std::string & text,int64_t offset,std::list<Accessibility::AccessibilityElementInfo> & output)4772  void FrameNode::SearchElementInfosByTextNG(int64_t elementId, const std::string& text, int64_t offset,
4773      std::list<Accessibility::AccessibilityElementInfo>& output)
4774  {
4775      if (pattern_) {
4776          pattern_->SearchElementInfosByText(elementId, text, offset, output);
4777      }
4778  }
4779  
FindFocusedExtensionElementInfoNG(int64_t elementId,int32_t focusType,int64_t offset,Accessibility::AccessibilityElementInfo & output)4780  void FrameNode::FindFocusedExtensionElementInfoNG(
4781      int64_t elementId, int32_t focusType, int64_t offset, Accessibility::AccessibilityElementInfo& output)
4782  {
4783      if (pattern_) {
4784          pattern_->FindFocusedElementInfo(elementId, focusType, offset, output);
4785      }
4786  }
4787  
FocusMoveSearchNG(int64_t elementId,int32_t direction,int64_t offset,Accessibility::AccessibilityElementInfo & output)4788  void FrameNode::FocusMoveSearchNG(
4789      int64_t elementId, int32_t direction, int64_t offset, Accessibility::AccessibilityElementInfo& output)
4790  {
4791      if (pattern_) {
4792          pattern_->FocusMoveSearch(elementId, direction, offset, output);
4793      }
4794  }
4795  
TransferExecuteAction(int64_t elementId,const std::map<std::string,std::string> & actionArguments,int32_t action,int64_t offset)4796  bool FrameNode::TransferExecuteAction(
4797      int64_t elementId, const std::map<std::string, std::string>& actionArguments, int32_t action, int64_t offset)
4798  {
4799      bool isExecuted = false;
4800      if (pattern_) {
4801          isExecuted = pattern_->TransferExecuteAction(elementId, actionArguments, action, offset);
4802      }
4803      return isExecuted;
4804  }
4805  
GetOnChildTouchTestRet(const std::vector<TouchTestInfo> & touchInfo)4806  TouchResult FrameNode::GetOnChildTouchTestRet(const std::vector<TouchTestInfo>& touchInfo)
4807  {
4808      TouchResult res;
4809      res.strategy = TouchTestStrategy::DEFAULT;
4810  
4811      auto func = GetOnTouchTestFunc();
4812      if (func == nullptr) {
4813          return res;
4814      }
4815      return func(touchInfo);
4816  }
4817  
GetOnTouchTestFunc()4818  OnChildTouchTestFunc FrameNode::GetOnTouchTestFunc()
4819  {
4820      auto gestureHub = eventHub_->GetGestureEventHub();
4821      if (gestureHub == nullptr) {
4822          return nullptr;
4823      }
4824      auto& func = gestureHub->GetOnTouchTestFunc();
4825      return func;
4826  }
4827  
CollectTouchInfos(const PointF & globalPoint,const PointF & parentRevertPoint,std::vector<TouchTestInfo> & touchInfos)4828  void FrameNode::CollectTouchInfos(
4829      const PointF& globalPoint, const PointF& parentRevertPoint, std::vector<TouchTestInfo>& touchInfos)
4830  {
4831      if (GetOnTouchTestFunc() == nullptr) {
4832          return;
4833      }
4834  
4835      for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
4836          const auto& child = iter->Upgrade();
4837          if (!child) {
4838              continue;
4839          }
4840  
4841          TouchTestInfo info;
4842          if (!child->GetInspectorId().has_value()) {
4843              continue;
4844          }
4845          info.id = child->GetInspectorId().value();
4846          info.windowPoint = globalPoint;
4847          info.currentCmpPoint = parentRevertPoint;
4848  
4849          auto renderContext = child->GetRenderContext();
4850          CHECK_NULL_VOID(renderContext);
4851          auto origRect = renderContext->GetPaintRectWithoutTransform();
4852          auto revertPoint = parentRevertPoint;
4853          renderContext->GetPointWithRevert(revertPoint);
4854          auto subRevertPoint = revertPoint - origRect.GetOffset();
4855          info.subCmpPoint = subRevertPoint;
4856  
4857          info.subRect = child->GetGeometryNode()->GetFrameRect();
4858  
4859          touchInfos.emplace_back(info);
4860      }
4861  }
4862  
GetDispatchFrameNode(const TouchResult & touchRes)4863  RefPtr<FrameNode> FrameNode::GetDispatchFrameNode(const TouchResult& touchRes)
4864  {
4865      if (touchRes.strategy != TouchTestStrategy::FORWARD_COMPETITION &&
4866          touchRes.strategy != TouchTestStrategy::FORWARD) {
4867          return nullptr;
4868      }
4869  
4870      for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
4871          const auto& child = iter->Upgrade();
4872          if (!child) {
4873              continue;
4874          }
4875          std::string id = child->GetInspectorId().value_or("");
4876          if ((!touchRes.id.empty()) && (touchRes.id == id)) {
4877              return child;
4878          }
4879      }
4880      return nullptr;
4881  }
4882  
CalculateCachedTransformRelativeOffset(uint64_t nanoTimestamp)4883  OffsetF FrameNode::CalculateCachedTransformRelativeOffset(uint64_t nanoTimestamp)
4884  {
4885      auto context = GetRenderContext();
4886      CHECK_NULL_RETURN(context, OffsetF());
4887      auto offset = context->GetPaintRectWithTransform().GetOffset();
4888  
4889      auto parent = GetAncestorNodeOfFrame(true);
4890      if (parent) {
4891          auto parentTimestampOffset = parent->GetCachedTransformRelativeOffset();
4892          if (parentTimestampOffset.first == nanoTimestamp) {
4893              auto result = offset + parentTimestampOffset.second;
4894              SetCachedTransformRelativeOffset({ nanoTimestamp, result });
4895              return result;
4896          }
4897          auto result = offset + parent->CalculateCachedTransformRelativeOffset(nanoTimestamp);
4898          SetCachedTransformRelativeOffset({ nanoTimestamp, result });
4899          return result;
4900      }
4901      SetCachedTransformRelativeOffset({ nanoTimestamp, offset });
4902      return offset;
4903  }
4904  
CalculateOffsetRelativeToWindow(uint64_t nanoTimestamp)4905  OffsetF FrameNode::CalculateOffsetRelativeToWindow(uint64_t nanoTimestamp)
4906  {
4907      auto currOffset = geometryNode_->GetFrameOffset();
4908      if (renderContext_ && renderContext_->GetPositionProperty()) {
4909          if (renderContext_->GetPositionProperty()->HasPosition()) {
4910              auto renderPosition =
4911                  ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
4912              currOffset.SetX(static_cast<float>(renderPosition.first));
4913              currOffset.SetY(static_cast<float>(renderPosition.second));
4914          }
4915      }
4916  
4917      auto parent = GetAncestorNodeOfFrame(true);
4918      if (parent) {
4919          auto parentTimestampOffset = parent->GetCachedGlobalOffset();
4920          if (parentTimestampOffset.first == nanoTimestamp) {
4921              auto result = currOffset + parentTimestampOffset.second;
4922              SetCachedGlobalOffset({ nanoTimestamp, result });
4923              return result;
4924          } else {
4925              auto result = currOffset + parent->CalculateOffsetRelativeToWindow(nanoTimestamp);
4926              SetCachedGlobalOffset({ nanoTimestamp, result });
4927              return result;
4928          }
4929      } else {
4930          SetCachedGlobalOffset({ nanoTimestamp, currOffset });
4931          return currOffset;
4932      }
4933  }
4934  
GetNodeContainer()4935  RefPtr<FrameNode> FrameNode::GetNodeContainer()
4936  {
4937      if (GetTag() == V2::NODE_CONTAINER_ETS_TAG) {
4938          return Claim(this);
4939      }
4940      auto parent = GetParent();
4941      while (parent && parent->GetTag() != V2::NODE_CONTAINER_ETS_TAG) {
4942          parent = parent->GetParent();
4943      }
4944      return AceType::DynamicCast<FrameNode>(parent);
4945  }
4946  
InitLastArea()4947  void FrameNode::InitLastArea()
4948  {
4949      if (!lastFrameRect_) {
4950          lastFrameRect_ = std::make_unique<RectF>();
4951      }
4952      if (!lastParentOffsetToWindow_) {
4953          lastParentOffsetToWindow_ = std::make_unique<OffsetF>();
4954      }
4955  }
4956  
SetParentLayoutConstraint(const SizeF & size) const4957  bool FrameNode::SetParentLayoutConstraint(const SizeF& size) const
4958  {
4959      LayoutConstraintF layoutConstraint;
4960      layoutConstraint.UpdatePercentReference(size);
4961      layoutConstraint.UpdateMaxSizeWithCheck(size);
4962      layoutConstraint.UpdateIllegalParentIdealSizeWithCheck(OptionalSize(size));
4963      layoutProperty_->UpdateParentLayoutConstraint(layoutConstraint);
4964      return true;
4965  }
4966  
ForceSyncGeometryNode()4967  void FrameNode::ForceSyncGeometryNode()
4968  {
4969      CHECK_NULL_VOID(renderContext_);
4970      oldGeometryNode_.Reset();
4971      renderContext_->SavePaintRect();
4972      renderContext_->SyncGeometryProperties(RawPtr(geometryNode_));
4973  }
4974  
GetCachedGlobalOffset() const4975  const std::pair<uint64_t, OffsetF>& FrameNode::GetCachedGlobalOffset() const
4976  {
4977      return cachedGlobalOffset_;
4978  }
4979  
SetCachedGlobalOffset(const std::pair<uint64_t,OffsetF> & timestampOffset)4980  void FrameNode::SetCachedGlobalOffset(const std::pair<uint64_t, OffsetF>& timestampOffset)
4981  {
4982      cachedGlobalOffset_ = timestampOffset;
4983  }
GetCachedTransformRelativeOffset() const4984  const std::pair<uint64_t, OffsetF>& FrameNode::GetCachedTransformRelativeOffset() const
4985  {
4986      return cachedTransformRelativeOffset_;
4987  }
4988  
SetCachedTransformRelativeOffset(const std::pair<uint64_t,OffsetF> & timestampOffset)4989  void FrameNode::SetCachedTransformRelativeOffset(const std::pair<uint64_t, OffsetF>& timestampOffset)
4990  {
4991      cachedTransformRelativeOffset_ = timestampOffset;
4992  }
4993  
PaintDebugBoundary(bool flag)4994  void FrameNode::PaintDebugBoundary(bool flag)
4995  {
4996      if (!isActive_) {
4997          return;
4998      }
4999      if (renderContext_) {
5000          renderContext_->PaintDebugBoundary(flag);
5001      }
5002  }
5003  
TriggerOnTouchIntercept(const TouchEvent & touchEvent)5004  HitTestMode FrameNode::TriggerOnTouchIntercept(const TouchEvent& touchEvent)
5005  {
5006      auto gestureHub = eventHub_->GetGestureEventHub();
5007      CHECK_NULL_RETURN(gestureHub, HitTestMode::HTMDEFAULT);
5008      auto onTouchIntercept = gestureHub->GetOnTouchIntercept();
5009      CHECK_NULL_RETURN(onTouchIntercept, HitTestMode::HTMDEFAULT);
5010      TouchEventInfo event("touchEvent");
5011      event.SetTimeStamp(touchEvent.time);
5012      event.SetDeviceId(touchEvent.deviceId);
5013      event.SetPointerEvent(touchEvent.pointerEvent);
5014      TouchLocationInfo changedInfo("onTouch", touchEvent.originalId);
5015      PointF lastLocalPoint(touchEvent.x, touchEvent.y);
5016      NGGestureRecognizer::Transform(lastLocalPoint, Claim(this), false, false);
5017      auto localX = static_cast<float>(lastLocalPoint.GetX());
5018      auto localY = static_cast<float>(lastLocalPoint.GetY());
5019      changedInfo.SetLocalLocation(Offset(localX, localY));
5020      changedInfo.SetGlobalLocation(Offset(touchEvent.x, touchEvent.y));
5021      changedInfo.SetScreenLocation(Offset(touchEvent.screenX, touchEvent.screenY));
5022      changedInfo.SetTouchType(touchEvent.type);
5023      changedInfo.SetForce(touchEvent.force);
5024      if (touchEvent.tiltX.has_value()) {
5025          changedInfo.SetTiltX(touchEvent.tiltX.value());
5026      }
5027      if (touchEvent.tiltY.has_value()) {
5028          changedInfo.SetTiltY(touchEvent.tiltY.value());
5029      }
5030      changedInfo.SetSourceTool(touchEvent.sourceTool);
5031      event.AddChangedTouchLocationInfo(std::move(changedInfo));
5032  
5033      AddTouchEventAllFingersInfo(event, touchEvent);
5034      event.SetSourceDevice(touchEvent.sourceType);
5035      event.SetForce(touchEvent.force);
5036      if (touchEvent.tiltX.has_value()) {
5037          event.SetTiltX(touchEvent.tiltX.value());
5038      }
5039      if (touchEvent.tiltY.has_value()) {
5040          event.SetTiltY(touchEvent.tiltY.value());
5041      }
5042      event.SetSourceTool(touchEvent.sourceTool);
5043      auto result = onTouchIntercept(event);
5044      SetHitTestMode(result);
5045      return result;
5046  }
5047  
AddTouchEventAllFingersInfo(TouchEventInfo & event,const TouchEvent & touchEvent)5048  void FrameNode::AddTouchEventAllFingersInfo(TouchEventInfo& event, const TouchEvent& touchEvent)
5049  {
5050      // all fingers collection
5051      for (const auto& item : touchEvent.pointers) {
5052          float globalX = item.x;
5053          float globalY = item.y;
5054          float screenX = item.screenX;
5055          float screenY = item.screenY;
5056          PointF localPoint(globalX, globalY);
5057          NGGestureRecognizer::Transform(localPoint, Claim(this), false, false);
5058          auto localX = static_cast<float>(localPoint.GetX());
5059          auto localY = static_cast<float>(localPoint.GetY());
5060          TouchLocationInfo info("onTouch", item.originalId);
5061          info.SetGlobalLocation(Offset(globalX, globalY));
5062          info.SetLocalLocation(Offset(localX, localY));
5063          info.SetScreenLocation(Offset(screenX, screenY));
5064          info.SetTouchType(touchEvent.type);
5065          info.SetForce(item.force);
5066          if (item.tiltX.has_value()) {
5067              info.SetTiltX(item.tiltX.value());
5068          }
5069          if (item.tiltY.has_value()) {
5070              info.SetTiltY(item.tiltY.value());
5071          }
5072          info.SetSourceTool(item.sourceTool);
5073          event.AddTouchLocationInfo(std::move(info));
5074      }
5075  }
5076  
AttachContext(PipelineContext * context,bool recursive)5077  void FrameNode::AttachContext(PipelineContext* context, bool recursive)
5078  {
5079      UINode::AttachContext(context, recursive);
5080      eventHub_->OnAttachContext(context);
5081      pattern_->OnAttachContext(context);
5082  }
5083  
DetachContext(bool recursive)5084  void FrameNode::DetachContext(bool recursive)
5085  {
5086      CHECK_NULL_VOID(context_);
5087      pattern_->OnDetachContext(context_);
5088      eventHub_->OnDetachContext(context_);
5089      UINode::DetachContext(recursive);
5090  }
5091  
ApplyFrameNodeTranformToRect(const RectF & rect,const RefPtr<FrameNode> & parent) const5092  RectF FrameNode::ApplyFrameNodeTranformToRect(const RectF& rect, const RefPtr<FrameNode>& parent) const
5093  {
5094      RectF newRect = rect;
5095      if (!parent) {
5096          return newRect;
5097      }
5098  
5099      auto parentRenderContext = parent->GetRenderContext();
5100      if (!parentRenderContext) {
5101          return newRect;
5102      }
5103  
5104      auto parentScale = parentRenderContext->GetTransformScale();
5105      auto offset = rect.GetOffset();
5106      if (parentScale) {
5107          newRect.SetWidth(rect.Width() * parentScale.value().x);
5108          newRect.SetHeight(rect.Height() * parentScale.value().y);
5109          offset = OffsetF(offset.GetX() * parentScale.value().x, offset.GetY() * parentScale.value().y);
5110      }
5111      offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
5112      newRect.SetOffset(offset);
5113      return newRect;
5114  }
5115  
GetVisibleRect(RectF & visibleRect,RectF & frameRect) const5116  void FrameNode::GetVisibleRect(RectF& visibleRect, RectF& frameRect) const
5117  {
5118      visibleRect = GetPaintRectWithTransform();
5119      frameRect = visibleRect;
5120      RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame(true);
5121      if (!parentUi) {
5122          visibleRect.SetWidth(0.0f);
5123          visibleRect.SetHeight(0.0f);
5124          return;
5125      }
5126      while (parentUi) {
5127          visibleRect = ApplyFrameNodeTranformToRect(visibleRect, parentUi);
5128          auto parentRect = parentUi->GetPaintRectWithTransform();
5129          visibleRect = visibleRect.Constrain(parentRect);
5130          if (visibleRect.IsEmpty()) {
5131              return;
5132          }
5133          frameRect = ApplyFrameNodeTranformToRect(frameRect, parentUi);
5134          parentUi = parentUi->GetAncestorNodeOfFrame(true);
5135      }
5136  }
5137  
AllowVisibleAreaCheck() const5138  bool FrameNode::AllowVisibleAreaCheck() const
5139  {
5140      return IsOnMainTree() || (pattern_ && pattern_->AllowVisibleAreaCheck());
5141  }
5142  
GetVisibleRectWithClip(RectF & visibleRect,RectF & visibleInnerRect,RectF & frameRect,bool withClip) const5143  void FrameNode::GetVisibleRectWithClip(RectF& visibleRect, RectF& visibleInnerRect, RectF& frameRect,
5144      bool withClip) const
5145  {
5146      visibleRect = GetPaintRectWithTransform();
5147      frameRect = visibleRect;
5148      visibleInnerRect = visibleRect;
5149      RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame(true);
5150      if (!AllowVisibleAreaCheck() || !parentUi || IsFrameDisappear()) {
5151          visibleRect.SetWidth(0.0f);
5152          visibleRect.SetHeight(0.0f);
5153          visibleInnerRect.SetWidth(0.0f);
5154          visibleInnerRect.SetHeight(0.0f);
5155          return;
5156      }
5157  
5158      while (parentUi) {
5159          visibleRect = ApplyFrameNodeTranformToRect(visibleRect, parentUi);
5160          auto parentRect = parentUi->GetPaintRectWithTransform();
5161          if (!visibleRect.IsEmpty()) {
5162              visibleRect = visibleRect.Constrain(parentRect);
5163          }
5164  
5165          if (isCalculateInnerVisibleRectClip_ || withClip) {
5166              visibleInnerRect = ApplyFrameNodeTranformToRect(visibleInnerRect, parentUi);
5167              auto parentContext = parentUi->GetRenderContext();
5168              if (!visibleInnerRect.IsEmpty() && ((parentContext && parentContext->GetClipEdge().value_or(false)) ||
5169                  parentUi->IsWindowBoundary() || parentUi->GetTag() == V2::ROOT_ETS_TAG)) {
5170                  visibleInnerRect = visibleInnerRect.Constrain(parentRect);
5171              }
5172          }
5173  
5174          if (visibleRect.IsEmpty() && (!(isCalculateInnerVisibleRectClip_ || withClip) || visibleInnerRect.IsEmpty())) {
5175              visibleInnerRect = visibleRect;
5176              return;
5177          }
5178          frameRect = ApplyFrameNodeTranformToRect(frameRect, parentUi);
5179          parentUi = parentUi->GetAncestorNodeOfFrame(true);
5180      }
5181  
5182      if (!(isCalculateInnerVisibleRectClip_ || withClip)) {
5183          visibleInnerRect = visibleRect;
5184      }
5185  }
5186  
GetCacheVisibleRect(uint64_t timestamp)5187  CacheVisibleRectResult FrameNode::GetCacheVisibleRect(uint64_t timestamp)
5188  {
5189      RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame(true);
5190      auto rectToParent = GetPaintRectWithTransform();
5191      auto scale = GetTransformScale();
5192  
5193      if (!parentUi || IsWindowBoundary()) {
5194          cachedVisibleRectResult_ = {timestamp,
5195              {rectToParent.GetOffset(), rectToParent, rectToParent, scale, rectToParent, rectToParent}};
5196          return cachedVisibleRectResult_.second;
5197      }
5198  
5199      if (parentUi->cachedVisibleRectResult_.first == timestamp) {
5200          auto parentCacheVisibleRectResult = parentUi->cachedVisibleRectResult_.second;
5201          return CalculateCacheVisibleRect(parentCacheVisibleRectResult, parentUi, rectToParent, scale, timestamp);
5202      }
5203  
5204      CacheVisibleRectResult parentCacheVisibleRectResult = parentUi->GetCacheVisibleRect(timestamp);
5205      return CalculateCacheVisibleRect(parentCacheVisibleRectResult, parentUi, rectToParent, scale, timestamp);
5206  }
5207  
CalculateCacheVisibleRect(CacheVisibleRectResult & parentCacheVisibleRect,const RefPtr<FrameNode> & parentUi,RectF & rectToParent,VectorF scale,uint64_t timestamp)5208  CacheVisibleRectResult FrameNode::CalculateCacheVisibleRect(CacheVisibleRectResult& parentCacheVisibleRect,
5209      const RefPtr<FrameNode>& parentUi, RectF& rectToParent, VectorF scale, uint64_t timestamp)
5210  {
5211      auto parentRenderContext = parentUi->GetRenderContext();
5212      OffsetF windowOffset;
5213      auto offset = rectToParent.GetOffset();
5214      if (parentRenderContext && parentRenderContext->GetTransformScale()) {
5215          auto parentScale = parentRenderContext->GetTransformScale();
5216          offset = OffsetF(offset.GetX() * parentScale.value().x, offset.GetY() * parentScale.value().y);
5217      }
5218      windowOffset = parentCacheVisibleRect.windowOffset + offset;
5219  
5220      RectF rect;
5221      rect.SetOffset(windowOffset);
5222      rect.SetWidth(rectToParent.Width() * parentCacheVisibleRect.cumulativeScale.x);
5223      rect.SetHeight(rectToParent.Height() * parentCacheVisibleRect.cumulativeScale.y);
5224  
5225      auto visibleRect = rect.Constrain(parentCacheVisibleRect.visibleRect);
5226      auto innerVisibleRect = rect;
5227      auto innerBoundaryRect = parentCacheVisibleRect.innerBoundaryRect;
5228      if (parentRenderContext && parentRenderContext->GetClipEdge().value_or(false)) {
5229          innerBoundaryRect = parentCacheVisibleRect.innerVisibleRect.Constrain(innerBoundaryRect);
5230      }
5231      innerVisibleRect = rect.Constrain(innerBoundaryRect);
5232  
5233      scale = {scale.x * parentCacheVisibleRect.cumulativeScale.x, scale.y * parentCacheVisibleRect.cumulativeScale.y};
5234      cachedVisibleRectResult_ = { timestamp,
5235          { windowOffset, visibleRect, innerVisibleRect, scale, rect, innerBoundaryRect } };
5236      return {windowOffset, visibleRect, innerVisibleRect, scale, rect, innerBoundaryRect};
5237  }
5238  
ChangeSensitiveStyle(bool isSensitive)5239  void FrameNode::ChangeSensitiveStyle(bool isSensitive)
5240  {
5241      pattern_->OnSensitiveStyleChange(isSensitive);
5242  }
5243  
IsContextTransparent()5244  bool FrameNode::IsContextTransparent()
5245  {
5246      ACE_SCOPED_TRACE("Transparent detection");
5247      const auto& rect = renderContext_->GetPaintRectWithTransform();
5248      auto width = rect.Width();
5249      auto height = rect.Height();
5250      if (renderContext_->GetOpacity().has_value() && renderContext_->GetOpacity().value() <= MIN_OPACITY) {
5251          return true;
5252      }
5253      if (layoutTags_.find(GetTag()) == layoutTags_.end()) {
5254          if (width > MIN_WIDTH && height > MIN_HEIGHT &&
5255              static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)) == 0) {
5256              return false;
5257          }
5258      } else {
5259          if (width > MIN_WIDTH && height > MIN_HEIGHT &&
5260              static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)) == 0 &&
5261              renderContext_->GetBackgroundColor()->ColorToString().compare("#00000000") != 0) {
5262              return false;
5263          }
5264      }
5265      for (const auto& item : GetChildren()) {
5266          if (!item->IsContextTransparent()) {
5267              return false;
5268          }
5269      }
5270      return true;
5271  }
5272  
GetOrRefreshRevertMatrixFromCache(bool forceRefresh)5273  Matrix4& FrameNode::GetOrRefreshRevertMatrixFromCache(bool forceRefresh)
5274  {
5275      auto pipeline = NG::PipelineContext::GetCurrentContext();
5276      CHECK_NULL_RETURN(pipeline, localRevertMatrix_);
5277      auto nanoTimestamp = pipeline->GetVsyncTime();
5278      auto rect = renderContext_->GetPaintRectWithoutTransform();
5279      // the caller is trying to refresh cache forcedly or the cache is invalid
5280      if (!isLocalRevertMatrixAvailable_ || forceRefresh || prePaintRect_ != rect ||
5281          getCacheNanoTime_ + MATRIX_CACHE_TIME_THRESHOLD < nanoTimestamp) {
5282          localRevertMatrix_ = renderContext_->GetRevertMatrix();
5283          isLocalRevertMatrixAvailable_ = true;
5284          getCacheNanoTime_ = nanoTimestamp;
5285          prePaintRect_ = rect;
5286          return localRevertMatrix_;
5287      }
5288  
5289      // cache valid
5290      return localRevertMatrix_;
5291  }
5292  
5293  // apply the matrix to the given point specified by dst
MapPointTo(PointF & dst,Matrix4 & matrix)5294  void FrameNode::MapPointTo(PointF& dst, Matrix4& matrix)
5295  {
5296      Point tmp(dst.GetX(), dst.GetY());
5297      auto transformPoint = matrix * tmp;
5298      dst.SetX(transformPoint.GetX());
5299      dst.SetY(transformPoint.GetY());
5300  }
5301  
SetSuggestOpIncMarked(bool flag)5302  void FrameNode::SetSuggestOpIncMarked(bool flag)
5303  {
5304      if (flag) {
5305          suggestOpIncByte_ |= SUGGEST_OPINC_MARKED_MASK;
5306      } else {
5307          suggestOpIncByte_ &= (~SUGGEST_OPINC_MARKED_MASK);
5308      }
5309  }
5310  
GetSuggestOpIncMarked()5311  bool FrameNode::GetSuggestOpIncMarked()
5312  {
5313      return (suggestOpIncByte_ & SUGGEST_OPINC_MARKED_MASK) > 0;
5314  }
5315  
SetCanSuggestOpInc(bool flag)5316  void FrameNode::SetCanSuggestOpInc(bool flag)
5317  {
5318      if (flag) {
5319          suggestOpIncByte_ |= CAN_SUGGEST_OPINC_MASK;
5320      } else {
5321          suggestOpIncByte_ &= (~CAN_SUGGEST_OPINC_MASK);
5322      }
5323  }
5324  
GetCanSuggestOpInc()5325  bool FrameNode::GetCanSuggestOpInc()
5326  {
5327      return (suggestOpIncByte_ & CAN_SUGGEST_OPINC_MASK) > 0;
5328  }
5329  
SetApplicationRenderGroupMarked(bool flag)5330  void FrameNode::SetApplicationRenderGroupMarked(bool flag)
5331  {
5332      if (flag) {
5333          suggestOpIncByte_ |= APP_RENDER_GROUP_MARKED_MASK;
5334      } else {
5335          suggestOpIncByte_ &= (~APP_RENDER_GROUP_MARKED_MASK);
5336      }
5337  }
5338  
GetApplicationRenderGroupMarked()5339  bool FrameNode::GetApplicationRenderGroupMarked()
5340  {
5341      return (suggestOpIncByte_ & APP_RENDER_GROUP_MARKED_MASK) > 0;
5342  }
5343  
SetSuggestOpIncActivatedOnce()5344  void FrameNode::SetSuggestOpIncActivatedOnce()
5345  {
5346      suggestOpIncByte_ |= SUGGEST_OPINC_ACTIVATED_ONCE;
5347  }
5348  
GetSuggestOpIncActivatedOnce()5349  bool FrameNode::GetSuggestOpIncActivatedOnce()
5350  {
5351      return (suggestOpIncByte_ & SUGGEST_OPINC_ACTIVATED_ONCE) > 0;
5352  }
5353  
SetOpIncGroupCheckedThrough(bool flag)5354  void FrameNode::SetOpIncGroupCheckedThrough(bool flag)
5355  {
5356      if (flag) {
5357          suggestOpIncByte_ |= SUGGEST_OPINC_CHECKED_THROUGH;
5358      } else {
5359          suggestOpIncByte_ &= (~SUGGEST_OPINC_CHECKED_THROUGH);
5360      }
5361  }
5362  
GetOpIncGroupCheckedThrough()5363  bool FrameNode::GetOpIncGroupCheckedThrough()
5364  {
5365      return (suggestOpIncByte_ & SUGGEST_OPINC_CHECKED_THROUGH) > 0;
5366  }
5367  
SetOpIncCheckedOnce()5368  void FrameNode::SetOpIncCheckedOnce()
5369  {
5370      suggestOpIncByte_ |= SUGGEST_OPINC_CHCKED_ONCE;
5371  }
GetOpIncCheckedOnce()5372  bool FrameNode::GetOpIncCheckedOnce()
5373  {
5374      return (suggestOpIncByte_ & SUGGEST_OPINC_CHCKED_ONCE) > 0;
5375  }
5376  
MarkSuggestOpIncGroup(bool suggest,bool calc)5377  bool FrameNode::MarkSuggestOpIncGroup(bool suggest, bool calc)
5378  {
5379      CHECK_NULL_RETURN(renderContext_, false);
5380      if (!GetSuggestOpIncMarked() && GetCanSuggestOpInc()) {
5381          renderContext_->SuggestOpIncNode(suggest, calc);
5382          SetSuggestOpIncMarked(true);
5383      }
5384      return true;
5385  }
5386  
IsOpIncValidNode(const SizeF & boundary,int32_t childNumber)5387  OPINC_TYPE_E FrameNode::IsOpIncValidNode(const SizeF& boundary, int32_t childNumber)
5388  {
5389      auto ret = GetPattern()->OpIncType();
5390      switch (ret) {
5391          case OPINC_NODE:
5392              SetCanSuggestOpInc(true);
5393              break;
5394          case OPINC_PARENT_POSSIBLE:
5395              break;
5396          case OPINC_NODE_POSSIBLE: {
5397              int32_t height = static_cast<int>(GetGeometryNode()->GetFrameSize().Height());
5398              int32_t width = static_cast<int>(GetGeometryNode()->GetFrameSize().Width());
5399              int32_t heightBoundary = static_cast<int>(boundary.Height() * HIGHT_RATIO_LIMIT);
5400              int32_t area = height * width;
5401              if (area >= MIN_OPINC_AREA && height <= heightBoundary) {
5402                  SetCanSuggestOpInc(true);
5403                  ret = OPINC_NODE;
5404              } else if (height > heightBoundary) {
5405                  ret = OPINC_PARENT_POSSIBLE;
5406              } else {
5407                  ret = OPINC_SUGGESTED_OR_EXCLUDED;
5408              }
5409              break;
5410          }
5411          default:
5412              break;
5413      }
5414      return ret;
5415  }
5416  
GetAllChildren()5417  ChildrenListWithGuard FrameNode::GetAllChildren()
5418  {
5419      // frameProxy_ never be null in frame node;
5420      return frameProxy_->GetCurrentFrameChildren();
5421  }
5422  
FindSuggestOpIncNode(std::string & path,const SizeF & boundary,int32_t depth)5423  OPINC_TYPE_E FrameNode::FindSuggestOpIncNode(std::string& path, const SizeF& boundary, int32_t depth)
5424  {
5425      if (GetSuggestOpIncActivatedOnce()) {
5426          return OPINC_SUGGESTED_OR_EXCLUDED;
5427      }
5428      SetSuggestOpIncActivatedOnce();
5429  
5430      if (GetApplicationRenderGroupMarked()) {
5431          return OPINC_INVALID;
5432      }
5433      auto status = IsOpIncValidNode(boundary);
5434      if (SystemProperties::GetDebugEnabled()) {
5435          const auto& hostTag = GetHostTag();
5436          path = path + " --> " + hostTag;
5437          LOGD("FindSuggestOpIncNode : %{public}s, with depth %{public}d, boundary: %{public}f, self: %{public}f, "
5438               "status: %{public}d",
5439              path.c_str(), depth, boundary.Height(), GetGeometryNode()->GetFrameSize().Height(), status);
5440      }
5441      if (status == OPINC_NODE) {
5442          MarkSuggestOpIncGroup(true, true);
5443          return OPINC_SUGGESTED_OR_EXCLUDED;
5444      } else if (status == OPINC_SUGGESTED_OR_EXCLUDED) {
5445          return OPINC_SUGGESTED_OR_EXCLUDED;
5446      } else if (status == OPINC_PARENT_POSSIBLE) {
5447          for (auto child : GetAllChildren()) {
5448              if (!child) {
5449                  continue;
5450              }
5451              auto frameNode = AceType::DynamicCast<FrameNode>(child);
5452              if (frameNode) {
5453                  frameNode->FindSuggestOpIncNode(path, boundary, depth + 1);
5454              }
5455          }
5456          return OPINC_PARENT_POSSIBLE;
5457      } else if (status == OPINC_INVALID) {
5458          return OPINC_INVALID;
5459      }
5460      return OPINC_SUGGESTED_OR_EXCLUDED;
5461  }
5462  
MarkAndCheckNewOpIncNode()5463  void FrameNode::MarkAndCheckNewOpIncNode()
5464  {
5465      auto parent = GetAncestorNodeOfFrame();
5466      CHECK_NULL_VOID(parent);
5467      if (parent->GetSuggestOpIncActivatedOnce() && !GetSuggestOpIncActivatedOnce()) {
5468          SetSuggestOpIncActivatedOnce();
5469          if (!parent->GetOpIncCheckedOnce()) {
5470              parent->SetOpIncCheckedOnce();
5471              auto status = IsOpIncValidNode(parent->GetGeometryNode()->GetFrameSize());
5472              if (status == OPINC_NODE) {
5473                  parent->SetOpIncGroupCheckedThrough(true);
5474              } else if (FrameNode::GetValidLeafChildNumber(Claim(this), THRESH_CHILD_NO) >= THRESH_CHILD_NO) {
5475                  parent->SetOpIncGroupCheckedThrough(true);
5476              } else {
5477                  parent->SetOpIncGroupCheckedThrough(false);
5478              }
5479          }
5480          if (parent->GetOpIncGroupCheckedThrough()) {
5481              SetCanSuggestOpInc(true);
5482              MarkSuggestOpIncGroup(true, true);
5483          }
5484      }
5485  }
5486  
GetValidLeafChildNumber(const RefPtr<FrameNode> & host,int32_t thresh)5487  int FrameNode::GetValidLeafChildNumber(const RefPtr<FrameNode>& host, int32_t thresh)
5488  {
5489      CHECK_NULL_RETURN(host, 0);
5490      auto total = 0;
5491      auto childSize = host->GetTotalChildCount();
5492      if (childSize < 1) {
5493          return 1;
5494      }
5495      for (auto i = 0; i < childSize; i++) {
5496          auto child = AceType::DynamicCast<FrameNode>(host->GetChildByIndex(i));
5497          if (!child) {
5498              continue;
5499          }
5500          total += GetValidLeafChildNumber(child, thresh);
5501          if (total >= thresh) {
5502              return total;
5503          }
5504      }
5505      return total;
5506  }
5507  
TriggerShouldParallelInnerWith(const ResponseLinkResult & currentRecognizers,const ResponseLinkResult & responseLinkRecognizers)5508  void FrameNode::TriggerShouldParallelInnerWith(
5509      const ResponseLinkResult& currentRecognizers, const ResponseLinkResult& responseLinkRecognizers)
5510  {
5511      auto gestureHub = eventHub_->GetGestureEventHub();
5512      CHECK_NULL_VOID(gestureHub);
5513      auto shouldBuiltInRecognizerParallelWithFunc = gestureHub->GetParallelInnerGestureToFunc();
5514      CHECK_NULL_VOID(shouldBuiltInRecognizerParallelWithFunc);
5515      std::map<GestureTypeName, std::vector<RefPtr<NGGestureRecognizer>>> sortedResponseLinkRecognizers;
5516  
5517      for (const auto& item : responseLinkRecognizers) {
5518          auto recognizer = AceType::DynamicCast<NGGestureRecognizer>(item);
5519          if (!recognizer) {
5520              continue;
5521          }
5522          auto type = recognizer->GetRecognizerType();
5523          sortedResponseLinkRecognizers[type].emplace_back(item);
5524      }
5525  
5526      for (const auto& item : currentRecognizers) {
5527          if (!item->IsSystemGesture() || item->GetRecognizerType() != GestureTypeName::PAN_GESTURE) {
5528              continue;
5529          }
5530          auto multiRecognizer = AceType::DynamicCast<MultiFingersRecognizer>(item);
5531          if (!multiRecognizer || multiRecognizer->GetTouchPointsSize() > 1) {
5532              continue;
5533          }
5534          auto iter = sortedResponseLinkRecognizers.find(item->GetRecognizerType());
5535          if (iter == sortedResponseLinkRecognizers.end() || iter->second.empty()) {
5536              continue;
5537          }
5538          auto result = shouldBuiltInRecognizerParallelWithFunc(item, iter->second);
5539          if (result && item != result) {
5540              item->SetBridgeMode(true);
5541              result->AddBridgeObj(item);
5542          }
5543      }
5544  }
5545  
ClearSubtreeLayoutAlgorithm(bool includeSelf,bool clearEntireTree)5546  void FrameNode::ClearSubtreeLayoutAlgorithm(bool includeSelf, bool clearEntireTree)
5547  {
5548      // return when reaches a child that has no layoutAlgorithm and no need to clear the entire tree
5549      if (!layoutAlgorithm_ && !clearEntireTree) {
5550          return;
5551      }
5552      // include Self might be false for the first ClearSubtreeLayoutAlgorithm enter,
5553      // but children should always include themselves
5554      if (includeSelf) {
5555          layoutAlgorithm_ = nullptr;
5556      }
5557      for (const auto& child : GetChildren()) {
5558          child->ClearSubtreeLayoutAlgorithm(true, clearEntireTree);
5559      }
5560  }
5561  
OnSyncGeometryFrameFinish(const RectF & paintRect)5562  void FrameNode::OnSyncGeometryFrameFinish(const RectF& paintRect)
5563  {
5564      if (syncedFramePaintRect_.has_value() && syncedFramePaintRect_.value() != paintRect) {
5565          AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_GEOMETRY_CHANGE);
5566          if (AnimationUtils::IsImplicitAnimationOpen()) {
5567              AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_START_ANIMATION);
5568          }
5569      }
5570      syncedFramePaintRect_ = paintRect;
5571  }
5572  
AddFrameNodeChangeInfoFlag(FrameNodeChangeInfoFlag changeFlag)5573  void FrameNode::AddFrameNodeChangeInfoFlag(FrameNodeChangeInfoFlag changeFlag)
5574  {
5575      if (changeInfoFlag_ == FRAME_NODE_CHANGE_INFO_NONE) {
5576          auto context = GetContext();
5577          CHECK_NULL_VOID(context);
5578          if (!context->AddChangedFrameNode(WeakClaim(this))) {
5579              return;
5580          }
5581      }
5582      changeInfoFlag_ = changeInfoFlag_ | changeFlag;
5583  }
5584  
RegisterNodeChangeListener()5585  void FrameNode::RegisterNodeChangeListener()
5586  {
5587      auto context = GetContext();
5588      CHECK_NULL_VOID(context);
5589      context->AddFrameNodeChangeListener(WeakClaim(this));
5590  }
5591  
UnregisterNodeChangeListener()5592  void FrameNode::UnregisterNodeChangeListener()
5593  {
5594      auto context = GetContext();
5595      CHECK_NULL_VOID(context);
5596      context->RemoveFrameNodeChangeListener(GetId());
5597  }
5598  
ProcessFrameNodeChangeFlag()5599  void FrameNode::ProcessFrameNodeChangeFlag()
5600  {
5601      auto changeFlag = FRAME_NODE_CHANGE_INFO_NONE;
5602      auto parent = Claim(this);
5603      while (parent) {
5604          if (parent->GetChangeInfoFlag() != FRAME_NODE_CHANGE_INFO_NONE) {
5605              changeFlag = changeFlag | parent->GetChangeInfoFlag();
5606          }
5607          parent = parent->GetAncestorNodeOfFrame(true);
5608      }
5609      if (changeFlag == FRAME_NODE_CHANGE_INFO_NONE) {
5610          return;
5611      }
5612      auto pattern = GetPattern();
5613      if (pattern) {
5614          pattern->OnFrameNodeChanged(changeFlag);
5615      }
5616  }
5617  
OnNodeTransformInfoUpdate(bool changed)5618  void FrameNode::OnNodeTransformInfoUpdate(bool changed)
5619  {
5620      if (!changed) {
5621          return;
5622      }
5623      AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_TRANSFORM_CHANGE);
5624      if (AnimationUtils::IsImplicitAnimationOpen()) {
5625          AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_START_ANIMATION);
5626      }
5627  }
5628  
OnNodeTransitionInfoUpdate()5629  void FrameNode::OnNodeTransitionInfoUpdate()
5630  {
5631      AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_TRANSITION_START);
5632  }
5633  
GetInspectorValue()5634  void FrameNode::GetInspectorValue()
5635  {
5636  #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
5637      if (GetTag() == V2::WEB_ETS_TAG) {
5638          UiSessionManager::GetInstance().WebTaskNumsChange(1);
5639          auto pattern = GetPattern<NG::WebPattern>();
5640          CHECK_NULL_VOID(pattern);
5641          auto cb = [](std::shared_ptr<JsonValue> value, int32_t webId) {
5642              UiSessionManager::GetInstance().AddValueForTree(webId, value->ToString());
5643              UiSessionManager::GetInstance().WebTaskNumsChange(-1);
5644          };
5645          pattern->GetAllWebAccessibilityNodeInfos(cb, GetId());
5646      }
5647  #endif
5648      UINode::GetInspectorValue();
5649  }
5650  
NotifyWebPattern(bool isRegister)5651  void FrameNode::NotifyWebPattern(bool isRegister)
5652  {
5653  #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(WEB_SUPPORTED) && defined(OHOS_PLATFORM)
5654      if (GetTag() == V2::WEB_ETS_TAG) {
5655          auto pattern = GetPattern<NG::WebPattern>();
5656          CHECK_NULL_VOID(pattern);
5657          if (isRegister) {
5658              auto callback = [](int64_t accessibilityId, const std::string data) {
5659                  UiSessionManager::GetInstance().ReportWebUnfocusEvent(accessibilityId, data);
5660              };
5661              pattern->RegisterTextBlurCallback(callback);
5662          } else {
5663              pattern->UnRegisterTextBlurCallback();
5664          }
5665      }
5666  #endif
5667      UINode::NotifyWebPattern(isRegister);
5668  }
5669  
NotifyChange(int32_t index,int32_t count,int64_t id,NotificationType notificationType)5670  void FrameNode::NotifyChange(int32_t index, int32_t count, int64_t id, NotificationType notificationType)
5671  {
5672      int32_t updateFrom = CalcAbsPosition(index, id);
5673      auto pattern = GetPattern();
5674      switch (notificationType) {
5675          case NotificationType::START_CHANGE_POSITION:
5676              ChildrenUpdatedFrom(updateFrom);
5677              break;
5678          case NotificationType::END_CHANGE_POSITION:
5679              pattern->NotifyDataChange(updateFrom, count);
5680              break;
5681          case NotificationType::START_AND_END_CHANGE_POSITION:
5682              ChildrenUpdatedFrom(updateFrom);
5683              pattern->NotifyDataChange(updateFrom, count);
5684              break;
5685          default:
5686              break;
5687      }
5688  }
5689  
5690  // for Grid refresh GridItems
ChildrenUpdatedFrom(int32_t index)5691  void FrameNode::ChildrenUpdatedFrom(int32_t index)
5692  {
5693      childrenUpdatedFrom_ = childrenUpdatedFrom_ >= 0 ? std::min(index, childrenUpdatedFrom_) : index;
5694  }
5695  
GetWindowPatternType() const5696  uint32_t FrameNode::GetWindowPatternType() const
5697  {
5698      CHECK_NULL_RETURN(pattern_, 0);
5699      return pattern_->GetWindowPatternType();
5700  }
5701  
ResetPredictNodes()5702  void FrameNode::ResetPredictNodes()
5703  {
5704      auto predictLayoutNode = std::move(predictLayoutNode_);
5705      for (auto& node : predictLayoutNode) {
5706          auto frameNode = node.Upgrade();
5707          if (frameNode && frameNode->isLayoutDirtyMarked_) {
5708              frameNode->isLayoutDirtyMarked_ = false;
5709          }
5710      }
5711  }
5712  
SetJSCustomProperty(std::function<bool ()> func,std::function<std::string (const std::string &)> getFunc)5713  void FrameNode::SetJSCustomProperty(std::function<bool()> func, std::function<std::string(const std::string&)> getFunc)
5714  {
5715      bool result = func();
5716      if (IsCNode()) {
5717          return;
5718      }
5719      if (result) {
5720          customPropertyMap_[UPDATE_FLAG_KEY] = "1";
5721      }
5722      if (!getCustomProperty_) {
5723          getCustomProperty_ = getFunc;
5724      }
5725  }
5726  
GetJSCustomProperty(const std::string & key,std::string & value)5727  bool FrameNode::GetJSCustomProperty(const std::string& key, std::string& value)
5728  {
5729      if (getCustomProperty_) {
5730          value = getCustomProperty_(key);
5731          return true;
5732      }
5733      return false;
5734  }
5735  
GetCapiCustomProperty(const std::string & key,std::string & value)5736  bool FrameNode::GetCapiCustomProperty(const std::string& key, std::string& value)
5737  {
5738      if (!IsCNode()) {
5739          return false;
5740      }
5741      auto iter = customPropertyMap_.find(key);
5742      if (iter != customPropertyMap_.end()) {
5743          value = iter->second;
5744          return true;
5745      }
5746      return false;
5747  }
5748  
AddCustomProperty(const std::string & key,const std::string & value)5749  void FrameNode::AddCustomProperty(const std::string& key, const std::string& value)
5750  {
5751      customPropertyMap_[key] = value;
5752  }
5753  
RemoveCustomProperty(const std::string & key)5754  void FrameNode::RemoveCustomProperty(const std::string& key)
5755  {
5756      auto iter = customPropertyMap_.find(key);
5757      if (iter != customPropertyMap_.end()) {
5758          customPropertyMap_.erase(iter);
5759      }
5760  }
5761  
GetCurrentPageRootNode()5762  RefPtr<UINode> FrameNode::GetCurrentPageRootNode()
5763  {
5764      auto pageNode = GetPageNode();
5765      CHECK_NULL_RETURN(pageNode, nullptr);
5766      auto jsView = pageNode->GetChildAtIndex(0);
5767      CHECK_NULL_RETURN(jsView, nullptr);
5768      if (jsView->GetTag() == V2::JS_VIEW_ETS_TAG) {
5769          auto rootNode = jsView->GetChildAtIndex(0);
5770          CHECK_NULL_RETURN(rootNode, nullptr);
5771          return rootNode;
5772      }
5773      return jsView;
5774  }
5775  
GetActiveChildren()5776  std::list<RefPtr<FrameNode>> FrameNode::GetActiveChildren()
5777  {
5778      std::list<RefPtr<FrameNode>> list;
5779      for (int32_t i = 0; i < TotalChildCount(); i++) {
5780          auto child = GetFrameNodeChildByIndex(i, false, false);
5781          if (child->IsActive()) {
5782              list.emplace_back(Referenced::Claim(child));
5783          }
5784      }
5785      return list;
5786  }
5787  
SetFrameNodeDestructorCallback(const std::function<void (int32_t)> && callback)5788  void FrameNode::SetFrameNodeDestructorCallback(const std::function<void(int32_t)>&& callback)
5789  {
5790      frameNodeDestructorCallback_ = callback;
5791  }
5792  
FireFrameNodeDestructorCallback()5793  void FrameNode::FireFrameNodeDestructorCallback()
5794  {
5795      if (frameNodeDestructorCallback_) {
5796          frameNodeDestructorCallback_(GetId());
5797      }
5798  }
5799  } // namespace OHOS::Ace::NG
5800