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