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