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