• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "base/geometry/dimension.h"
19 #include "base/geometry/ng/point_t.h"
20 #include "base/log/ace_trace.h"
21 #include "base/log/dump_log.h"
22 #include "base/log/log_wrapper.h"
23 #include "base/memory/ace_type.h"
24 #include "base/memory/referenced.h"
25 #include "base/thread/cancelable_callback.h"
26 #include "base/thread/task_executor.h"
27 #include "base/utils/system_properties.h"
28 #include "base/utils/time_util.h"
29 #include "base/utils/utils.h"
30 #include "core/common/ace_application_info.h"
31 #include "core/common/container.h"
32 #include "core/components/common/layout/constants.h"
33 #include "core/components/common/layout/grid_system_manager.h"
34 #include "core/components_ng/base/frame_scene_status.h"
35 #include "core/components_ng/base/inspector.h"
36 #include "core/components_ng/base/ui_node.h"
37 #include "core/components_ng/event/gesture_event_hub.h"
38 #include "core/components_ng/event/target_component.h"
39 #include "core/components_ng/layout/layout_algorithm.h"
40 #include "core/components_ng/layout/layout_wrapper.h"
41 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
42 #include "core/components_ng/pattern/pattern.h"
43 #include "core/components_ng/property/measure_property.h"
44 #include "core/components_ng/property/measure_utils.h"
45 #include "core/components_ng/property/property.h"
46 #include "core/components_ng/render/paint_wrapper.h"
47 #include "core/components_ng/syntax/lazy_for_each_node.h"
48 #include "core/components_v2/inspector/inspector_constants.h"
49 #include "core/event/touch_event.h"
50 #include "core/gestures/gesture_info.h"
51 #include "core/pipeline_ng/pipeline_context.h"
52 #include "core/pipeline_ng/ui_task_scheduler.h"
53 
54 namespace {
55 constexpr double VISIBLE_RATIO_MIN = 0.0;
56 constexpr double VISIBLE_RATIO_MAX = 1.0;
57 constexpr int32_t SUBSTR_LENGTH = 3;
58 const char DIMENSION_UNIT_VP[] = "vp";
59 const char FORM_COMPONENT_TAG[] = "FormComponent";
60 } // namespace
61 namespace OHOS::Ace::NG {
62 
63 class FramePorxy {
64 public:
65     struct FrameChildNode {
66         RefPtr<UINode> node;
67         uint32_t startIndex = 0;
68         uint32_t count = 0;
69     };
70 
71     struct RecursionGuard {
72         FramePorxy* proxy_;
73         bool inUse_;
RecursionGuardOHOS::Ace::NG::FramePorxy::RecursionGuard74         explicit RecursionGuard(FramePorxy* proxy) : proxy_(proxy), inUse_(proxy->inUse_)
75         {
76             proxy_->inUse_ = true;
77         }
~RecursionGuardOHOS::Ace::NG::FramePorxy::RecursionGuard78         ~RecursionGuard()
79         {
80             proxy_->inUse_ = inUse_;
81             if (!proxy_->inUse_ && proxy_->delayReset_) {
82                 proxy_->ResetChildren(proxy_->needResetChild_);
83             }
84         }
85     };
86 
GetGuard()87     RecursionGuard GetGuard()
88     {
89         return RecursionGuard{this};
90     }
91 
FramePorxy(FrameNode * frameNode)92     explicit FramePorxy(FrameNode* frameNode) : hostNode_(frameNode) {}
93 
Build()94     void Build()
95     {
96         if (hostNode_ == nullptr || !children_.empty()) {
97             return;
98         }
99         totalCount_ = 0;
100         auto children = hostNode_->GetChildren();
101         int32_t startIndex = 0;
102         int32_t count = 0;
103         for (const auto& child : children) {
104             count = child->FrameCount();
105             children_.push_back({ child, startIndex, count });
106             startIndex += count;
107             totalCount_ += count;
108         }
109         cursor_ = children_.begin();
110     }
111 
AddFrameNode(const RefPtr<UINode> & UiNode,std::list<RefPtr<LayoutWrapper>> & allFrameNodeChildren,std::map<uint32_t,RefPtr<LayoutWrapper>> & partFrameNodeChildren,uint32_t & count)112     static void AddFrameNode(const RefPtr<UINode>& UiNode, std::list<RefPtr<LayoutWrapper>>& allFrameNodeChildren,
113         std::map<uint32_t, RefPtr<LayoutWrapper>>& partFrameNodeChildren, uint32_t& count)
114     {
115         auto frameNode = AceType::DynamicCast<FrameNode>(UiNode);
116         if (frameNode) {
117             allFrameNodeChildren.emplace_back(frameNode);
118             partFrameNodeChildren[count++] = frameNode;
119             return;
120         }
121         auto lazyForEachNode = AceType::DynamicCast<LazyForEachNode>(UiNode);
122         if (lazyForEachNode) {
123             lazyForEachNode->BuildAllChildren();
124         } else {
125             auto customNode = AceType::DynamicCast<CustomNode>(UiNode);
126             if (customNode) {
127                 customNode->Render();
128             }
129         }
130         for (const auto& child : UiNode->GetChildren()) {
131             auto frameNode = AceType::DynamicCast<FrameNode>(child);
132             if (frameNode) {
133                 allFrameNodeChildren.emplace_back(frameNode);
134                 partFrameNodeChildren[count++] = frameNode;
135                 continue;
136             }
137             AddFrameNode(child, allFrameNodeChildren, partFrameNodeChildren, count);
138         }
139     }
140 
GetAllFrameChildren()141     const std::list<RefPtr<LayoutWrapper>>& GetAllFrameChildren()
142     {
143         if (!allFrameNodeChildren_.empty()) {
144             return allFrameNodeChildren_;
145         }
146         Build();
147         {
148             uint32_t count = 0;
149             auto guard = GetGuard();
150             for (const auto& child : children_) {
151                 AddFrameNode(child.node, allFrameNodeChildren_, partFrameNodeChildren_, count);
152             }
153         }
154         return allFrameNodeChildren_;
155     }
156 
FindFrameNodeByIndex(uint32_t index,bool needBuild)157     RefPtr<LayoutWrapper> FindFrameNodeByIndex(uint32_t index, bool needBuild)
158     {
159         while (cursor_ != children_.end()) {
160             if (cursor_->startIndex > index) {
161                 cursor_--;
162                 continue;
163             }
164 
165             if (cursor_->startIndex + cursor_->count > index) {
166                 auto frameNode = AceType::DynamicCast<FrameNode>(
167                     cursor_->node->GetFrameChildByIndex(index - cursor_->startIndex, needBuild));
168                 return frameNode;
169             }
170             cursor_++;
171             if (cursor_ == children_.end()) {
172                 cursor_ = children_.begin();
173                 return nullptr;
174             }
175         }
176         return nullptr;
177     }
178 
GetFrameNodeByIndex(uint32_t index,bool needBuild)179     RefPtr<LayoutWrapper> GetFrameNodeByIndex(uint32_t index, bool needBuild)
180     {
181         auto itor = partFrameNodeChildren_.find(index);
182         if (itor == partFrameNodeChildren_.end()) {
183             Build();
184             auto child = FindFrameNodeByIndex(index, needBuild);
185             if (child) {
186                 partFrameNodeChildren_[index] = child;
187                 return child;
188             }
189             return nullptr;
190         }
191         return itor->second;
192     }
193 
ResetChildren(bool needResetChild=false)194     void ResetChildren(bool needResetChild = false)
195     {
196         if (inUse_) {
197             delayReset_ = true;
198             needResetChild_ = needResetChild;
199             return;
200         }
201         delayReset_ = false;
202         allFrameNodeChildren_.clear();
203         partFrameNodeChildren_.clear();
204         totalCount_ = 0;
205         if (needResetChild) {
206             children_.clear();
207             cursor_ = children_.begin();
208         }
209     }
210 
RemoveChildInRenderTree(uint32_t index)211     void RemoveChildInRenderTree(uint32_t index)
212     {
213         auto itor = partFrameNodeChildren_.find(index);
214         if (itor == partFrameNodeChildren_.end()) {
215             return;
216         }
217         itor->second->SetActive(false);
218         partFrameNodeChildren_.erase(itor);
219         while (cursor_ != children_.end()) {
220             if (cursor_->startIndex > index) {
221                 cursor_--;
222                 continue;
223             }
224             if (cursor_->startIndex + cursor_->count > index) {
225                 cursor_->node->DoRemoveChildInRenderTree(index - cursor_->startIndex);
226                 return;
227             }
228             cursor_++;
229             if (cursor_ == children_.end()) {
230                 cursor_ = children_.begin();
231                 return;
232             }
233         }
234     }
235 
SetActiveChildRange(int32_t start,int32_t end)236     void SetActiveChildRange(int32_t start, int32_t end)
237     {
238         for (auto itor = partFrameNodeChildren_.begin(); itor != partFrameNodeChildren_.end();) {
239             int32_t index = itor->first;
240             if ((start <= end && index >= start && index <= end) ||
241                 (start > end && (index <= end || start <= index))) {
242                 itor->second->SetActive(true);
243                 itor++;
244             } else {
245                 itor->second->SetActive(false);
246                 partFrameNodeChildren_.erase(itor++);
247             }
248         }
249         auto guard = GetGuard();
250         for (const auto& child : children_) {
251             child.node->DoSetActiveChildRange(start - child.startIndex, end - child.startIndex);
252         }
253     }
254 
RemoveAllChildInRenderTree()255     void RemoveAllChildInRenderTree()
256     {
257         SetAllChildrenInActive();
258         ResetChildren();
259         Build();
260         auto guard = GetGuard();
261         for (const auto& child : children_) {
262             child.node->DoRemoveChildInRenderTree(0, true);
263         }
264     }
265 
GetTotalCount()266     uint32_t GetTotalCount()
267     {
268         return totalCount_;
269     }
270 
SetAllChildrenInActive()271     void SetAllChildrenInActive()
272     {
273         auto guard = GetGuard();
274         for (const auto& child : partFrameNodeChildren_) {
275             child.second->SetActive(false);
276         }
277     }
278 
Dump()279     std::string Dump()
280     {
281         if (totalCount_ == 0) {
282             return "totalCount is 0";
283         }
284         std::string info = "FrameChildNode:[";
285         auto guard = GetGuard();
286         for (const auto& child : children_) {
287             info += std::to_string(child.node->GetId());
288             info += "-";
289             info += std::to_string(child.startIndex);
290             info += "-";
291             info += std::to_string(child.count);
292             info += ",";
293         }
294         info += "] partFrameNodeChildren:[";
295         for (const auto& child : partFrameNodeChildren_) {
296             info += std::to_string(child.second->GetHostNode()->GetId());
297             info += ",";
298         }
299         info += "] TotalCount:";
300         info += std::to_string(totalCount_);
301         return info;
302     }
303 
SetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)304     void SetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
305     {
306         auto guard = GetGuard();
307         for (const auto& child : children_) {
308             child.node->OnSetCacheCount(cacheCount, itemConstraint);
309         }
310     }
311 
312 private:
313     std::list<FrameChildNode> children_;
314     std::list<FrameChildNode>::iterator cursor_ = children_.begin();
315     std::list<RefPtr<LayoutWrapper>> allFrameNodeChildren_;
316     std::map<uint32_t, RefPtr<LayoutWrapper>> partFrameNodeChildren_;
317     uint32_t totalCount_ = 0;
318     FrameNode* hostNode_ { nullptr };
319     bool inUse_ = false;
320     bool delayReset_ = false;
321     bool needResetChild_ = false;
322 }; // namespace OHOS::Ace::NG
323 
FrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)324 FrameNode::FrameNode(const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
325     : UINode(tag, nodeId, isRoot), LayoutWrapper(WeakClaim(this)), pattern_(pattern),
326       frameProxy_(std::make_unique<FramePorxy>(this))
327 {
328     renderContext_->InitContext(IsRootNode(), pattern_->GetContextParam());
329     paintProperty_ = pattern->CreatePaintProperty();
330     layoutProperty_ = pattern->CreateLayoutProperty();
331     eventHub_ = pattern->CreateEventHub();
332     accessibilityProperty_ = pattern->CreateAccessibilityProperty();
333     // first create make layout property dirty.
334     layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
335     layoutProperty_->SetHost(WeakClaim(this));
336 }
337 
~FrameNode()338 FrameNode::~FrameNode()
339 {
340     for (const auto& destroyCallback : destroyCallbacks_) {
341         destroyCallback();
342     }
343 
344     pattern_->DetachFromFrameNode(this);
345     if (IsOnMainTree()) {
346         OnDetachFromMainTree(false);
347     }
348     TriggerVisibleAreaChangeCallback(true);
349     visibleAreaUserCallbacks_.clear();
350     visibleAreaInnerCallbacks_.clear();
351     if (eventHub_) {
352         eventHub_->ClearOnAreaChangedInnerCallbacks();
353     }
354     auto pipeline = PipelineContext::GetCurrentContext();
355     if (pipeline) {
356         pipeline->RemoveOnAreaChangeNode(GetId());
357         pipeline->RemoveVisibleAreaChangeNode(GetId());
358         pipeline->ChangeMouseStyle(GetId(), MouseFormat::DEFAULT);
359         pipeline->FreeMouseStyleHoldNode(GetId());
360         pipeline->RemoveStoredNode(GetRestoreId());
361         auto dragManager = pipeline->GetDragDropManager();
362         if (dragManager) {
363             dragManager->RemoveDragFrameNode(GetId());
364             dragManager->UnRegisterDragStatusListener(GetId());
365         }
366         auto frameRateManager = pipeline->GetFrameRateManager();
367         if (frameRateManager) {
368             frameRateManager->RemoveNodeRate(GetId());
369         }
370     }
371 }
372 
CreateFrameNodeWithTree(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern)373 RefPtr<FrameNode> FrameNode::CreateFrameNodeWithTree(
374     const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern)
375 {
376     auto newChild = CreateFrameNode(tag, nodeId, pattern, true);
377     newChild->SetDepth(1);
378     return newChild;
379 }
380 
GetOrCreateFrameNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)381 RefPtr<FrameNode> FrameNode::GetOrCreateFrameNode(
382     const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
383 {
384     auto frameNode = GetFrameNode(tag, nodeId);
385     if (frameNode) {
386         return frameNode;
387     }
388     auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
389     return CreateFrameNode(tag, nodeId, pattern);
390 }
391 
GetFrameNode(const std::string & tag,int32_t nodeId)392 RefPtr<FrameNode> FrameNode::GetFrameNode(const std::string& tag, int32_t nodeId)
393 {
394     auto frameNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(nodeId);
395     CHECK_NULL_RETURN(frameNode, nullptr);
396     if (frameNode->GetTag() != tag) {
397         ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
398         auto parent = frameNode->GetParent();
399         if (parent) {
400             parent->RemoveChild(frameNode);
401         }
402         return nullptr;
403     }
404     return frameNode;
405 }
406 
CreateFrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)407 RefPtr<FrameNode> FrameNode::CreateFrameNode(
408     const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
409 {
410     auto frameNode = MakeRefPtr<FrameNode>(tag, nodeId, pattern, isRoot);
411     ElementRegister::GetInstance()->AddUINode(frameNode);
412     frameNode->InitializePatternAndContext();
413     return frameNode;
414 }
415 
ProcessOffscreenNode(const RefPtr<FrameNode> & node)416 void FrameNode::ProcessOffscreenNode(const RefPtr<FrameNode>& node)
417 {
418     CHECK_NULL_VOID(node);
419     node->ProcessOffscreenTask();
420     node->MarkModifyDone();
421     node->UpdateLayoutPropertyFlag();
422     node->SetActive();
423     node->isLayoutDirtyMarked_ = true;
424     auto pipeline = PipelineContext::GetCurrentContext();
425     node->CreateLayoutTask();
426     if (pipeline) {
427         pipeline->FlushSyncGeometryNodeTasks();
428     }
429 
430     auto paintProperty = node->GetPaintProperty<PaintProperty>();
431     auto wrapper = node->CreatePaintWrapper();
432     if (wrapper != nullptr) {
433         wrapper->FlushRender();
434     }
435     paintProperty->CleanDirty();
436     CHECK_NULL_VOID(pipeline);
437     pipeline->FlushMessages();
438     node->SetActive(false);
439 }
440 
InitializePatternAndContext()441 void FrameNode::InitializePatternAndContext()
442 {
443     eventHub_->AttachHost(WeakClaim(this));
444     pattern_->AttachToFrameNode(WeakClaim(this));
445     accessibilityProperty_->SetHost(WeakClaim(this));
446     renderContext_->SetRequestFrame([weak = WeakClaim(this)] {
447         auto frameNode = weak.Upgrade();
448         CHECK_NULL_VOID(frameNode);
449         if (frameNode->IsOnMainTree()) {
450             auto context = frameNode->GetContext();
451             CHECK_NULL_VOID(context);
452             context->RequestFrame();
453             return;
454         }
455         frameNode->hasPendingRequest_ = true;
456     });
457     renderContext_->SetHostNode(WeakClaim(this));
458     // Initialize FocusHub
459     if (pattern_->GetFocusPattern().GetFocusType() != FocusType::DISABLE) {
460         GetOrCreateFocusHub();
461     }
462 }
463 
DumpCommonInfo()464 void FrameNode::DumpCommonInfo()
465 {
466     if (!geometryNode_->GetFrameRect().ToString().compare(renderContext_->GetPaintRectWithoutTransform().ToString())) {
467         DumpLog::GetInstance().AddDesc(std::string("FrameRect: ").append(geometryNode_->GetFrameRect().ToString()));
468     }
469     if (renderContext_->GetBackgroundColor()->ColorToString().compare("#00000000") != 0) {
470         DumpLog::GetInstance().AddDesc(
471             std::string("BackgroundColor: ").append(renderContext_->GetBackgroundColor()->ColorToString()));
472     }
473     if (geometryNode_->GetParentLayoutConstraint().has_value())
474         DumpLog::GetInstance().AddDesc(std::string("ParentLayoutConstraint: ")
475             .append(geometryNode_->GetParentLayoutConstraint().value().ToString()));
476     if (!(NearZero(GetOffsetRelativeToWindow().GetY()) && NearZero(GetOffsetRelativeToWindow().GetX()))) {
477         DumpLog::GetInstance().AddDesc(std::string("top: ")
478                                            .append(std::to_string(GetOffsetRelativeToWindow().GetY()))
479                                            .append(" left: ")
480                                            .append(std::to_string(GetOffsetRelativeToWindow().GetX())));
481     }
482     if (static_cast<int32_t>(IsActive()) != 1) {
483         DumpLog::GetInstance().AddDesc(
484             std::string("Active: ").append(std::to_string(static_cast<int32_t>(IsActive()))));
485     }
486 
487     if (static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)) != 0) {
488         DumpLog::GetInstance().AddDesc(std::string("Visible: ")
489                                            .append(std::to_string(static_cast<int32_t>(
490                                                layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)))));
491     }
492     if (layoutProperty_->GetPaddingProperty()) {
493         DumpLog::GetInstance().AddDesc(
494             std::string("Padding: ").append(layoutProperty_->GetPaddingProperty()->ToString().c_str()));
495     }
496     if (layoutProperty_->GetBorderWidthProperty()) {
497         DumpLog::GetInstance().AddDesc(
498             std::string("Border: ").append(layoutProperty_->GetBorderWidthProperty()->ToString().c_str()));
499     }
500     if (layoutProperty_->GetMarginProperty()) {
501         DumpLog::GetInstance().AddDesc(
502             std::string("Margin: ").append(layoutProperty_->GetMarginProperty()->ToString().c_str()));
503     }
504     if (layoutProperty_->GetCalcLayoutConstraint()) {
505         DumpLog::GetInstance().AddDesc(std::string("User defined constraint: ")
506                                            .append(layoutProperty_->GetCalcLayoutConstraint()->ToString().c_str()));
507     }
508     if (!propInspectorId_->empty()) {
509         DumpLog::GetInstance().AddDesc(std::string("compid: ").append(propInspectorId_.value_or("")));
510     }
511     if (layoutProperty_->GetPaddingProperty() || layoutProperty_->GetBorderWidthProperty() ||
512         layoutProperty_->GetMarginProperty() || layoutProperty_->GetCalcLayoutConstraint()) {
513         DumpLog::GetInstance().AddDesc(
514             std::string("ContentConstraint: ")
515                 .append(layoutProperty_->GetContentLayoutConstraint().has_value() ?
516                             layoutProperty_->GetContentLayoutConstraint().value().ToString() : "NA"));
517     }
518     DumpOverlayInfo();
519     if (frameProxy_->Dump().compare("totalCount is 0") != 0) {
520         DumpLog::GetInstance().AddDesc(std::string("FrameProxy: ").append(frameProxy_->Dump().c_str()));
521     }
522 }
523 
DumpOverlayInfo()524 void FrameNode::DumpOverlayInfo()
525 {
526     if (!layoutProperty_->IsOverlayNode()) {
527         return;
528     }
529     DumpLog::GetInstance().AddDesc(std::string("IsOverlayNode: ").append(std::string("true")));
530     Dimension offsetX, offsetY;
531     layoutProperty_->GetOverlayOffset(offsetX, offsetY);
532     DumpLog::GetInstance().AddDesc(
533         std::string("OverlayOffset: ").append(offsetX.ToString()).append(std::string(", ")).append(offsetY.ToString()));
534 }
535 
DumpInfo()536 void FrameNode::DumpInfo()
537 {
538     DumpCommonInfo();
539     if (pattern_) {
540         pattern_->DumpInfo();
541     }
542     if (renderContext_) {
543         renderContext_->DumpInfo();
544     }
545 }
546 
DumpAdvanceInfo()547 void FrameNode::DumpAdvanceInfo()
548 {
549     DumpCommonInfo();
550     if (pattern_) {
551         pattern_->DumpInfo();
552         pattern_->DumpAdvanceInfo();
553     }
554     if (renderContext_) {
555         renderContext_->DumpInfo();
556         renderContext_->DumpAdvanceInfo();
557     }
558 }
559 
DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap)560 void FrameNode::DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap)
561 {
562     if (pattern_) {
563         pattern_->DumpViewDataPageNode(viewDataWrap);
564     }
565 }
566 
CheckAutoSave()567 bool FrameNode::CheckAutoSave()
568 {
569     if (pattern_) {
570         return pattern_->CheckAutoSave();
571     }
572     return false;
573 }
574 
FocusToJsonValue(std::unique_ptr<JsonValue> & json) const575 void FrameNode::FocusToJsonValue(std::unique_ptr<JsonValue>& json) const
576 {
577     bool enabled = true;
578     bool focusable = false;
579     bool focused = false;
580     bool defaultFocus = false;
581     bool groupDefaultFocus = false;
582     bool focusOnTouch = false;
583     int32_t tabIndex = 0;
584     auto focusHub = GetFocusHub();
585     if (focusHub) {
586         enabled = focusHub->IsEnabled();
587         focusable = focusHub->IsFocusable();
588         focused = focusHub->IsCurrentFocus();
589         defaultFocus = focusHub->IsDefaultFocus();
590         groupDefaultFocus = focusHub->IsDefaultGroupFocus();
591         focusOnTouch = focusHub->IsFocusOnTouch().value_or(false);
592         tabIndex = focusHub->GetTabIndex();
593     }
594     json->Put("enabled", enabled);
595     json->Put("focusable", focusable);
596     json->Put("focused", focused);
597     json->Put("defaultFocus", defaultFocus);
598     json->Put("groupDefaultFocus", groupDefaultFocus);
599     json->Put("focusOnTouch", focusOnTouch);
600     json->Put("tabIndex", tabIndex);
601 }
602 
MouseToJsonValue(std::unique_ptr<JsonValue> & json) const603 void FrameNode::MouseToJsonValue(std::unique_ptr<JsonValue>& json) const
604 {
605     std::string hoverEffect = "HoverEffect.Auto";
606     auto inputEventHub = GetOrCreateInputEventHub();
607     if (inputEventHub) {
608         hoverEffect = inputEventHub->GetHoverEffectStr();
609     }
610     json->Put("hoverEffect", hoverEffect.c_str());
611 }
612 
TouchToJsonValue(std::unique_ptr<JsonValue> & json) const613 void FrameNode::TouchToJsonValue(std::unique_ptr<JsonValue>& json) const
614 {
615     bool touchable = true;
616     bool monopolizeEvents = false;
617     std::string hitTestMode = "HitTestMode.Default";
618     auto gestureEventHub = GetOrCreateGestureEventHub();
619     std::vector<DimensionRect> responseRegion;
620     std::vector<DimensionRect> mouseResponseRegion;
621     if (gestureEventHub) {
622         touchable = gestureEventHub->GetTouchable();
623         hitTestMode = gestureEventHub->GetHitTestModeStr();
624         responseRegion = gestureEventHub->GetResponseRegion();
625         mouseResponseRegion = gestureEventHub->GetMouseResponseRegion();
626         monopolizeEvents = gestureEventHub->GetMonopolizeEvents();
627     }
628     json->Put("touchable", touchable);
629     json->Put("hitTestBehavior", hitTestMode.c_str());
630     json->Put("monopolizeEvents", monopolizeEvents);
631     auto jsArr = JsonUtil::CreateArray(true);
632     for (int32_t i = 0; i < static_cast<int32_t>(responseRegion.size()); ++i) {
633         auto iStr = std::to_string(i);
634         jsArr->Put(iStr.c_str(), responseRegion[i].ToJsonString().c_str());
635     }
636     json->Put("responseRegion", jsArr);
637     for (int32_t i = 0; i < static_cast<int32_t>(mouseResponseRegion.size()); ++i) {
638         auto iStr = std::to_string(i);
639         jsArr->Put(iStr.c_str(), mouseResponseRegion[i].ToJsonString().c_str());
640     }
641     json->Put("mouseResponseRegion", jsArr);
642 }
643 
GeometryNodeToJsonValue(std::unique_ptr<JsonValue> & json) const644 void FrameNode::GeometryNodeToJsonValue(std::unique_ptr<JsonValue>& json) const
645 {
646     bool hasIdealWidth = false;
647     bool hasIdealHeight = false;
648     if (layoutProperty_ && layoutProperty_->GetCalcLayoutConstraint()) {
649         auto selfIdealSize = layoutProperty_->GetCalcLayoutConstraint()->selfIdealSize;
650         hasIdealWidth = selfIdealSize.has_value() && selfIdealSize.value().Width().has_value();
651         hasIdealHeight = selfIdealSize.has_value() && selfIdealSize.value().Height().has_value();
652     }
653 
654     auto jsonSize = json->GetValue("size");
655     if (!hasIdealWidth) {
656         auto idealWidthVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Width()).ConvertToVp());
657         auto widthStr =
658             (idealWidthVpStr.substr(0, idealWidthVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP);
659         json->Put("width", widthStr.c_str());
660         if (jsonSize) {
661             jsonSize->Put("width", widthStr.c_str());
662         }
663     }
664 
665     if (!hasIdealHeight) {
666         auto idealHeightVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Height()).ConvertToVp());
667         auto heightStr =
668             (idealHeightVpStr.substr(0, idealHeightVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP);
669         json->Put("height", heightStr.c_str());
670         if (jsonSize) {
671             jsonSize->Put("height", heightStr.c_str());
672         }
673     }
674 }
675 
ToJsonValue(std::unique_ptr<JsonValue> & json) const676 void FrameNode::ToJsonValue(std::unique_ptr<JsonValue>& json) const
677 {
678     if (renderContext_) {
679         renderContext_->ToJsonValue(json);
680     }
681     // scrollable in AccessibilityProperty
682     ACE_PROPERTY_TO_JSON_VALUE(accessibilityProperty_, AccessibilityProperty);
683     ACE_PROPERTY_TO_JSON_VALUE(layoutProperty_, LayoutProperty);
684     ACE_PROPERTY_TO_JSON_VALUE(paintProperty_, PaintProperty);
685     ACE_PROPERTY_TO_JSON_VALUE(pattern_, Pattern);
686     if (eventHub_) {
687         eventHub_->ToJsonValue(json);
688     }
689     FocusToJsonValue(json);
690     MouseToJsonValue(json);
691     TouchToJsonValue(json);
692     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
693 #if defined(PREVIEW)
694         GeometryNodeToJsonValue(json);
695 #endif
696     } else {
697         GeometryNodeToJsonValue(json);
698     }
699     json->Put("id", propInspectorId_.value_or("").c_str());
700 }
701 
FromJson(const std::unique_ptr<JsonValue> & json)702 void FrameNode::FromJson(const std::unique_ptr<JsonValue>& json)
703 {
704     if (renderContext_) {
705         renderContext_->FromJson(json);
706     }
707     accessibilityProperty_->FromJson(json);
708     layoutProperty_->FromJson(json);
709     paintProperty_->FromJson(json);
710     pattern_->FromJson(json);
711     if (eventHub_) {
712         eventHub_->FromJson(json);
713     }
714 }
715 
OnAttachToMainTree(bool recursive)716 void FrameNode::OnAttachToMainTree(bool recursive)
717 {
718     eventHub_->FireOnAppear();
719     renderContext_->OnNodeAppear(recursive);
720     pattern_->OnAttachToMainTree();
721     // node may have been measured before AttachToMainTree
722     if (geometryNode_->GetParentLayoutConstraint().has_value() && !UseOffscreenProcess()) {
723         layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE_SELF);
724     }
725 
726     UINode::OnAttachToMainTree(recursive);
727 
728     if (!hasPendingRequest_) {
729         return;
730     }
731     auto context = GetContext();
732     CHECK_NULL_VOID(context);
733     context->RequestFrame();
734     hasPendingRequest_ = false;
735 }
736 
OnAttachToBuilderNode(NodeStatus nodeStatus)737 void FrameNode::OnAttachToBuilderNode(NodeStatus nodeStatus)
738 {
739     pattern_->OnAttachToBuilderNode(nodeStatus);
740 }
741 
OnConfigurationUpdate(const ConfigurationChange & configurationChange)742 void FrameNode::OnConfigurationUpdate(const ConfigurationChange& configurationChange)
743 {
744     if (configurationChange.languageUpdate) {
745         pattern_->OnLanguageConfigurationUpdate();
746         MarkModifyDone();
747         MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
748     }
749     if (configurationChange.colorModeUpdate) {
750         pattern_->OnColorConfigurationUpdate();
751         MarkModifyDone();
752         MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
753     }
754     if (configurationChange.directionUpdate) {
755         pattern_->OnDirectionConfigurationUpdate();
756         MarkModifyDone();
757         MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
758     }
759     if (configurationChange.dpiUpdate) {
760         pattern_->OnDpiConfigurationUpdate();
761         MarkModifyDone();
762         MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
763     }
764     if (configurationChange.fontUpdate) {
765         MarkModifyDone();
766         MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
767     }
768     if (configurationChange.iconUpdate) {
769         pattern_->OnIconConfigurationUpdate();
770         MarkModifyDone();
771         MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
772     }
773     if (configurationChange.skinUpdate) {
774         MarkModifyDone();
775         MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
776     }
777 }
778 
OnVisibleChange(bool isVisible)779 void FrameNode::OnVisibleChange(bool isVisible)
780 {
781     pattern_->OnVisibleChange(isVisible);
782     UpdateChildrenVisible(isVisible);
783 }
784 
OnDetachFromMainTree(bool recursive)785 void FrameNode::OnDetachFromMainTree(bool recursive)
786 {
787     if (auto focusHub = GetFocusHub()) {
788         focusHub->RemoveSelf();
789     }
790     pattern_->OnDetachFromMainTree();
791     eventHub_->FireOnDisappear();
792     renderContext_->OnNodeDisappear(recursive);
793 }
794 
SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper> & dirty)795 void FrameNode::SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper>& dirty)
796 {
797     CHECK_NULL_VOID(dirty);
798 
799     // update new layout constrain.
800     layoutProperty_->UpdateLayoutConstraint(dirty->GetLayoutProperty());
801 
802     // active change flag judge.
803     SetActive(dirty->IsActive());
804     if (!isActive_) {
805         return;
806     }
807 
808     // update layout size.
809     bool frameSizeChange = geometryNode_->GetFrameSize() != dirty->GetGeometryNode()->GetFrameSize();
810     bool frameOffsetChange = geometryNode_->GetFrameOffset() != dirty->GetGeometryNode()->GetFrameOffset();
811     bool contentSizeChange = geometryNode_->GetContentSize() != dirty->GetGeometryNode()->GetContentSize();
812     bool contentOffsetChange = geometryNode_->GetContentOffset() != dirty->GetGeometryNode()->GetContentOffset();
813 
814     SetGeometryNode(dirty->GetGeometryNode());
815 
816     const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
817     if (geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this))) {
818         geometryTransition->DidLayout(dirty);
819         if (geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
820             isLayoutDirtyMarked_ = true;
821         }
822     } else if (frameSizeChange || frameOffsetChange || HasPositionProp() ||
823                (pattern_->GetContextParam().has_value() && contentSizeChange)) {
824         renderContext_->SyncGeometryProperties(RawPtr(dirty->GetGeometryNode()));
825     }
826 
827     // clean layout flag.
828     layoutProperty_->CleanDirty();
829     DirtySwapConfig config { frameSizeChange, frameOffsetChange, contentSizeChange, contentOffsetChange };
830     // check if need to paint content.
831     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
832     CHECK_NULL_VOID(layoutAlgorithmWrapper);
833     config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure() || dirty->SkipMeasureContent();
834     config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
835     if ((config.skipMeasure == false) && (config.skipLayout == false) && GetInspectorId().has_value()) {
836         auto pipeline = PipelineContext::GetCurrentContext();
837         CHECK_NULL_VOID(pipeline);
838         pipeline->OnLayoutCompleted(GetInspectorId()->c_str());
839     }
840     auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(dirty, config);
841     // TODO: temp use and need to delete.
842     needRerender = needRerender || pattern_->OnDirtyLayoutWrapperSwap(dirty, config.skipMeasure, config.skipLayout);
843     if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
844         MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
845     }
846 
847     // update border.
848     if (layoutProperty_->GetBorderWidthProperty()) {
849         if (!renderContext_->HasBorderColor()) {
850             BorderColorProperty borderColorProperty;
851             borderColorProperty.SetColor(Color::BLACK);
852             renderContext_->UpdateBorderColor(borderColorProperty);
853         }
854         if (!renderContext_->HasBorderStyle()) {
855             BorderStyleProperty borderStyleProperty;
856             borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
857             renderContext_->UpdateBorderStyle(borderStyleProperty);
858         }
859         if (layoutProperty_->GetLayoutConstraint().has_value()) {
860             renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
861                 ScaleProperty::CreateScaleProperty(),
862                 layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
863         } else {
864             renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
865                 ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
866         }
867     }
868 
869     // update background
870     if (builderFunc_) {
871         auto builderNode = builderFunc_();
872         auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
873             AceType::MakeRefPtr<LinearLayoutPattern>(true));
874         if (builderNode) {
875             builderNode->MountToParent(columnNode);
876         }
877         SetBackgroundLayoutConstraint(columnNode);
878         renderContext_->CreateBackgroundPixelMap(columnNode);
879         builderFunc_ = nullptr;
880         backgroundNode_ = columnNode;
881     }
882 
883     // update focus state
884     auto focusHub = GetFocusHub();
885     if (focusHub && focusHub->IsCurrentFocus()) {
886         focusHub->ClearFocusState(false);
887         focusHub->PaintFocusState(false);
888     }
889 
890     // rebuild child render node.
891     RebuildRenderContextTree();
892 }
893 
SetBackgroundLayoutConstraint(const RefPtr<FrameNode> & customNode)894 void FrameNode::SetBackgroundLayoutConstraint(const RefPtr<FrameNode>& customNode)
895 {
896     CHECK_NULL_VOID(customNode);
897     LayoutConstraintF layoutConstraint;
898     layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
899     layoutConstraint.percentReference.SetWidth(geometryNode_->GetFrameSize().Width());
900     layoutConstraint.percentReference.SetHeight(geometryNode_->GetFrameSize().Height());
901     layoutConstraint.maxSize.SetWidth(geometryNode_->GetFrameSize().Width());
902     layoutConstraint.maxSize.SetHeight(geometryNode_->GetFrameSize().Height());
903     customNode->GetGeometryNode()->SetParentLayoutConstraint(layoutConstraint);
904 }
905 
AdjustGridOffset()906 void FrameNode::AdjustGridOffset()
907 {
908     if (!isActive_) {
909         return;
910     }
911     if (layoutProperty_->UpdateGridOffset(Claim(this))) {
912         renderContext_->UpdateOffset(OffsetT<Dimension>());
913         renderContext_->UpdateAnchor(OffsetT<Dimension>());
914         renderContext_->SyncGeometryProperties(RawPtr(GetGeometryNode()));
915     }
916 }
917 
ClearUserOnAreaChange()918 void FrameNode::ClearUserOnAreaChange()
919 {
920     if (eventHub_) {
921         eventHub_->ClearUserOnAreaChanged();
922     }
923 }
924 
SetOnAreaChangeCallback(OnAreaChangedFunc && callback)925 void FrameNode::SetOnAreaChangeCallback(OnAreaChangedFunc&& callback)
926 {
927     InitLastArea();
928     eventHub_->SetOnAreaChanged(std::move(callback));
929 }
930 
TriggerOnAreaChangeCallback(uint64_t nanoTimestamp)931 void FrameNode::TriggerOnAreaChangeCallback(uint64_t nanoTimestamp)
932 {
933     if (!IsActive()) {
934         return;
935     }
936     if ((eventHub_->HasOnAreaChanged() || eventHub_->HasInnerOnAreaChanged()) && lastFrameRect_ &&
937         lastParentOffsetToWindow_) {
938         auto currFrameRect = geometryNode_->GetFrameRect();
939         auto currParentOffsetToWindow = CalculateOffsetRelativeToWindow(nanoTimestamp) - currFrameRect.GetOffset();
940         if (currFrameRect != *lastFrameRect_ || currParentOffsetToWindow != *lastParentOffsetToWindow_) {
941             if (eventHub_->HasInnerOnAreaChanged()) {
942                 eventHub_->FireInnerOnAreaChanged(
943                     *lastFrameRect_, *lastParentOffsetToWindow_, currFrameRect, currParentOffsetToWindow);
944             }
945             if (eventHub_->HasOnAreaChanged()) {
946                 eventHub_->FireOnAreaChanged(
947                     *lastFrameRect_, *lastParentOffsetToWindow_, currFrameRect, currParentOffsetToWindow);
948             }
949             *lastFrameRect_ = currFrameRect;
950             *lastParentOffsetToWindow_ = currParentOffsetToWindow;
951         }
952     }
953     pattern_->OnAreaChangedInner();
954 }
955 
TriggerVisibleAreaChangeCallback(bool forceDisappear)956 void FrameNode::TriggerVisibleAreaChangeCallback(bool forceDisappear)
957 {
958     auto context = PipelineContext::GetCurrentContext();
959     CHECK_NULL_VOID(context);
960 
961     bool isFrameDisappear = forceDisappear || !context->GetOnShow() || !IsOnMainTree() || !IsVisible();
962     if (!isFrameDisappear) {
963         bool curFrameIsActive = isActive_;
964         bool curIsVisible = IsVisible();
965         auto parent = GetParent();
966         while (parent) {
967             auto parentFrame = AceType::DynamicCast<FrameNode>(parent);
968             if (!parentFrame) {
969                 parent = parent->GetParent();
970                 continue;
971             }
972             if (!parentFrame->isActive_) {
973                 curFrameIsActive = false;
974                 break;
975             }
976             if (!parentFrame->IsVisible()) {
977                 curIsVisible = false;
978                 break;
979             }
980             parent = parent->GetParent();
981         }
982         isFrameDisappear = !curIsVisible || !curFrameIsActive;
983     }
984 
985     if (isFrameDisappear) {
986         if (!NearEqual(lastVisibleRatio_, VISIBLE_RATIO_MIN)) {
987             ProcessAllVisibleCallback(visibleAreaUserCallbacks_, VISIBLE_RATIO_MIN);
988             ProcessAllVisibleCallback(visibleAreaInnerCallbacks_, VISIBLE_RATIO_MIN);
989             lastVisibleRatio_ = VISIBLE_RATIO_MIN;
990         }
991         return;
992     }
993 
994     if (GetTag() == FORM_COMPONENT_TAG && visibleAreaUserCallbacks_.empty() && !visibleAreaInnerCallbacks_.empty()) {
995         ProcessAllVisibleCallback(visibleAreaInnerCallbacks_, VISIBLE_RATIO_MAX);
996         lastVisibleRatio_ = VISIBLE_RATIO_MAX;
997         return;
998     }
999 
1000     auto frameRect = GetTransformRectRelativeToWindow();
1001     auto visibleRect = frameRect;
1002     RectF parentRect;
1003     auto parentUi = GetAncestorNodeOfFrame(true);
1004     if (!parentUi) {
1005         visibleRect.SetWidth(0.0f);
1006         visibleRect.SetHeight(0.0f);
1007     }
1008     while (parentUi) {
1009         parentRect = parentUi->GetTransformRectRelativeToWindow();
1010         visibleRect = visibleRect.Constrain(parentRect);
1011         parentUi = parentUi->GetAncestorNodeOfFrame(true);
1012     }
1013 
1014     double currentVisibleRatio =
1015         std::clamp(CalculateCurrentVisibleRatio(visibleRect, frameRect), VISIBLE_RATIO_MIN, VISIBLE_RATIO_MAX);
1016     if (!NearEqual(currentVisibleRatio, lastVisibleRatio_)) {
1017         ProcessAllVisibleCallback(visibleAreaUserCallbacks_, currentVisibleRatio);
1018         ProcessAllVisibleCallback(visibleAreaInnerCallbacks_, currentVisibleRatio);
1019         lastVisibleRatio_ = currentVisibleRatio;
1020     }
1021 }
1022 
CalculateCurrentVisibleRatio(const RectF & visibleRect,const RectF & renderRect)1023 double FrameNode::CalculateCurrentVisibleRatio(const RectF& visibleRect, const RectF& renderRect)
1024 {
1025     if (!visibleRect.IsValid() || !renderRect.IsValid()) {
1026         return 0.0;
1027     }
1028     return visibleRect.Width() * visibleRect.Height() / (renderRect.Width() * renderRect.Height());
1029 }
1030 
ProcessAllVisibleCallback(std::unordered_map<double,VisibleCallbackInfo> & visibleAreaCallbacks,double currentVisibleRatio)1031 void FrameNode::ProcessAllVisibleCallback(
1032     std::unordered_map<double, VisibleCallbackInfo>& visibleAreaCallbacks, double currentVisibleRatio)
1033 {
1034     bool isHandled = false;
1035     bool isVisible = false;
1036     for (auto& nodeCallbackInfo : visibleAreaCallbacks) {
1037         auto callbackRatio = nodeCallbackInfo.first;
1038         auto callbackIsVisible = nodeCallbackInfo.second.isCurrentVisible;
1039         if (GreatNotEqual(currentVisibleRatio, callbackRatio) && !callbackIsVisible) {
1040             nodeCallbackInfo.second.isCurrentVisible = true;
1041             isVisible = (!isHandled) ? true : isVisible;
1042             isHandled = true;
1043             continue;
1044         }
1045 
1046         if (LessNotEqual(currentVisibleRatio, callbackRatio) && callbackIsVisible) {
1047             nodeCallbackInfo.second.isCurrentVisible = false;
1048             isVisible = (!isHandled) ? false : isVisible;
1049             isHandled = true;
1050             continue;
1051         }
1052 
1053         if (NearEqual(currentVisibleRatio, callbackRatio) && NearEqual(callbackRatio, VISIBLE_RATIO_MIN)) {
1054             nodeCallbackInfo.second.isCurrentVisible = false;
1055             isVisible = (!isHandled) ? false : isVisible;
1056             isHandled = true;
1057         } else if (NearEqual(currentVisibleRatio, callbackRatio) && NearEqual(callbackRatio, VISIBLE_RATIO_MAX)) {
1058             nodeCallbackInfo.second.isCurrentVisible = true;
1059             isVisible = (!isHandled) ? true : isVisible;
1060             isHandled = true;
1061         }
1062     }
1063 
1064     OnVisibleAreaChangeCallback(visibleAreaCallbacks, isVisible, currentVisibleRatio, isHandled);
1065 }
1066 
OnVisibleAreaChangeCallback(std::unordered_map<double,VisibleCallbackInfo> & visibleAreaCallbacks,bool visibleType,double currentVisibleRatio,bool isHandled)1067 void FrameNode::OnVisibleAreaChangeCallback(
1068     std::unordered_map<double, VisibleCallbackInfo>& visibleAreaCallbacks,
1069     bool visibleType, double currentVisibleRatio, bool isHandled)
1070 {
1071     auto iter = visibleAreaCallbacks.begin();
1072     if (isHandled && iter != visibleAreaCallbacks.end() && iter->second.callback) {
1073         auto callback = iter->second.callback;
1074         callback(visibleType, currentVisibleRatio);
1075     }
1076 }
1077 
SetActive(bool active)1078 void FrameNode::SetActive(bool active)
1079 {
1080     bool activeChanged = false;
1081     if (active && !isActive_) {
1082         pattern_->OnActive();
1083         isActive_ = true;
1084         activeChanged = true;
1085     }
1086     if (!active && isActive_) {
1087         pattern_->OnInActive();
1088         isActive_ = false;
1089         activeChanged = true;
1090     }
1091     if (activeChanged) {
1092         auto parent = GetAncestorNodeOfFrame();
1093         if (parent) {
1094             parent->MarkNeedSyncRenderTree();
1095         }
1096     }
1097 }
1098 
SetGeometryNode(const RefPtr<GeometryNode> & node)1099 void FrameNode::SetGeometryNode(const RefPtr<GeometryNode>& node)
1100 {
1101     geometryNode_ = node;
1102 }
1103 
CreateLayoutTask(bool forceUseMainThread)1104 void FrameNode::CreateLayoutTask(bool forceUseMainThread)
1105 {
1106     if (!isLayoutDirtyMarked_) {
1107         return;
1108     }
1109     SetRootMeasureNode(true);
1110     UpdateLayoutPropertyFlag();
1111     SetSkipSyncGeometryNode(false);
1112     {
1113         ACE_SCOPED_TRACE("CreateTaskMeasure[%s][self:%d][parent:%d]", GetTag().c_str(), GetId(),
1114             GetParent() ? GetParent()->GetId() : 0);
1115         Measure(GetLayoutConstraint());
1116     }
1117     {
1118         ACE_SCOPED_TRACE("CreateTaskLayout[%s][self:%d][parent:%d]", GetTag().c_str(), GetId(),
1119             GetParent() ? GetParent()->GetId() : 0);
1120         Layout();
1121     }
1122     SetRootMeasureNode(false);
1123 }
1124 
CreateRenderTask(bool forceUseMainThread)1125 std::optional<UITask> FrameNode::CreateRenderTask(bool forceUseMainThread)
1126 {
1127     if (!isRenderDirtyMarked_) {
1128         return std::nullopt;
1129     }
1130     auto wrapper = CreatePaintWrapper();
1131     CHECK_NULL_RETURN(wrapper, std::nullopt);
1132     auto task = [weak = WeakClaim(this), wrapper, paintProperty = paintProperty_]() {
1133         auto self = weak.Upgrade();
1134         ACE_SCOPED_TRACE("FrameNode[%s][id:%d]::RenderTask", self->GetTag().c_str(), self->GetId());
1135         wrapper->FlushRender();
1136         paintProperty->CleanDirty();
1137 
1138         if (self->GetInspectorId()) {
1139             auto pipeline = PipelineContext::GetCurrentContext();
1140             CHECK_NULL_VOID(pipeline);
1141             pipeline->SetNeedRenderNode(self);
1142         }
1143     };
1144     if (forceUseMainThread || wrapper->CheckShouldRunOnMain()) {
1145         return UITask(std::move(task), MAIN_TASK);
1146     }
1147     return UITask(std::move(task), wrapper->CanRunOnWhichThread());
1148 }
1149 
GetLayoutConstraint() const1150 LayoutConstraintF FrameNode::GetLayoutConstraint() const
1151 {
1152     if (geometryNode_->GetParentLayoutConstraint().has_value()) {
1153         return geometryNode_->GetParentLayoutConstraint().value();
1154     }
1155     LayoutConstraintF layoutConstraint;
1156     layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
1157     auto rootWidth = PipelineContext::GetCurrentRootWidth();
1158     auto rootHeight = PipelineContext::GetCurrentRootHeight();
1159     layoutConstraint.percentReference.SetWidth(rootWidth);
1160     layoutConstraint.percentReference.SetHeight(rootHeight);
1161     layoutConstraint.maxSize.SetWidth(rootWidth);
1162     layoutConstraint.maxSize.SetHeight(rootHeight);
1163     return layoutConstraint;
1164 }
1165 
GetParentGlobalOffset() const1166 OffsetF FrameNode::GetParentGlobalOffset() const
1167 {
1168     auto parent = GetAncestorNodeOfFrame();
1169     if (!parent) {
1170         return { 0.0f, 0.0f };
1171     }
1172     return parent->geometryNode_->GetParentGlobalOffset();
1173 }
1174 
UpdateLayoutPropertyFlag()1175 void FrameNode::UpdateLayoutPropertyFlag()
1176 {
1177     auto selfFlag = layoutProperty_->GetPropertyChangeFlag();
1178     if (!CheckUpdateByChildRequest(selfFlag)) {
1179         return;
1180     }
1181     if (CheckForceParentMeasureFlag(selfFlag)) {
1182         return;
1183     }
1184     auto flag = PROPERTY_UPDATE_NORMAL;
1185     const auto& children = GetChildren();
1186     for (const auto& child : children) {
1187         child->UpdateLayoutPropertyFlag();
1188         child->AdjustParentLayoutFlag(flag);
1189         if (CheckForceParentMeasureFlag(selfFlag)) {
1190             break;
1191         }
1192     }
1193     if (CheckForceParentMeasureFlag(flag)) {
1194         layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
1195     }
1196 }
1197 
ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeFlag)1198 void FrameNode::ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeFlag)
1199 {
1200     layoutProperty_->UpdatePropertyChangeFlag(propertyChangeFlag);
1201 }
1202 
AdjustParentLayoutFlag(PropertyChangeFlag & flag)1203 void FrameNode::AdjustParentLayoutFlag(PropertyChangeFlag& flag)
1204 {
1205     flag = flag | layoutProperty_->GetPropertyChangeFlag();
1206 }
1207 
CreateLayoutWrapper(bool forceMeasure,bool forceLayout)1208 RefPtr<LayoutWrapperNode> FrameNode::CreateLayoutWrapper(bool forceMeasure, bool forceLayout)
1209 {
1210     return UpdateLayoutWrapper(nullptr, forceMeasure, forceLayout);
1211 }
1212 
UpdateLayoutWrapper(RefPtr<LayoutWrapperNode> layoutWrapper,bool forceMeasure,bool forceLayout)1213 RefPtr<LayoutWrapperNode> FrameNode::UpdateLayoutWrapper(
1214     RefPtr<LayoutWrapperNode> layoutWrapper, bool forceMeasure, bool forceLayout)
1215 {
1216     CHECK_NULL_RETURN(layoutProperty_, nullptr);
1217     CHECK_NULL_RETURN(pattern_, nullptr);
1218     if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
1219         if (!layoutWrapper) {
1220             layoutWrapper =
1221                 MakeRefPtr<LayoutWrapperNode>(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
1222         } else {
1223             layoutWrapper->Update(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
1224         }
1225         layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
1226         isLayoutDirtyMarked_ = false;
1227         return layoutWrapper;
1228     }
1229 
1230     pattern_->BeforeCreateLayoutWrapper();
1231     if (forceMeasure) {
1232         layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
1233     }
1234     if (forceLayout) {
1235         layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
1236     }
1237     auto flag = layoutProperty_->GetPropertyChangeFlag();
1238     // It is necessary to copy the layoutProperty property to prevent the layoutProperty property from being
1239     // modified during the layout process, resulting in the problem of judging whether the front-end setting value
1240     // changes the next time js is executed.
1241     if (!layoutWrapper) {
1242         layoutWrapper =
1243             MakeRefPtr<LayoutWrapperNode>(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
1244     } else {
1245         layoutWrapper->Update(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
1246     }
1247     do {
1248         if (CheckNeedMeasure(flag) || forceMeasure) {
1249             layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm()));
1250             bool forceChildMeasure = CheckMeasureFlag(flag) || CheckMeasureSelfAndChildFlag(flag) || forceMeasure;
1251             UpdateChildrenLayoutWrapper(layoutWrapper, forceChildMeasure, false);
1252             break;
1253         }
1254         if (CheckNeedLayout(flag) || forceLayout) {
1255             layoutWrapper->SetLayoutAlgorithm(
1256                 MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm(), true, false));
1257             UpdateChildrenLayoutWrapper(layoutWrapper, false, false);
1258             break;
1259         }
1260         layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
1261     } while (false);
1262     // check position flag.
1263     layoutWrapper->SetOutOfLayout(renderContext_->HasPosition());
1264     layoutWrapper->SetActive(isActive_);
1265     layoutWrapper->SetIsOverlayNode(layoutProperty_->IsOverlayNode());
1266     isLayoutDirtyMarked_ = false;
1267     return layoutWrapper;
1268 }
1269 
UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapperNode> & self,bool forceMeasure,bool forceLayout)1270 void FrameNode::UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapperNode>& self, bool forceMeasure, bool forceLayout)
1271 {
1272     const auto& children = GetChildren();
1273     for (const auto& child : children) {
1274         child->AdjustLayoutWrapperTree(self, forceMeasure, forceLayout);
1275     }
1276 }
1277 
AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode> & parent,bool forceMeasure,bool forceLayout)1278 void FrameNode::AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode>& parent, bool forceMeasure, bool forceLayout)
1279 {
1280     ACE_DCHECK(parent);
1281     CHECK_NULL_VOID(layoutProperty_);
1282     const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
1283     if (geometryTransition != nullptr && geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
1284         return;
1285     }
1286     auto layoutWrapper = CreateLayoutWrapper(forceMeasure, forceLayout);
1287     parent->AppendChild(layoutWrapper, layoutProperty_->IsOverlayNode());
1288 }
1289 
CreatePaintWrapper()1290 RefPtr<PaintWrapper> FrameNode::CreatePaintWrapper()
1291 {
1292     pattern_->BeforeCreatePaintWrapper();
1293     isRenderDirtyMarked_ = false;
1294     auto paintMethod = pattern_->CreateNodePaintMethod();
1295     // It is necessary to copy the layoutProperty property to prevent the paintProperty_ property from being
1296     // modified during the paint process, resulting in the problem of judging whether the front-end setting value
1297     // changes the next time js is executed.
1298     if (paintMethod) {
1299         auto paintWrapper = MakeRefPtr<PaintWrapper>(renderContext_, geometryNode_->Clone(), paintProperty_->Clone());
1300         paintWrapper->SetNodePaintMethod(paintMethod);
1301         return paintWrapper;
1302     }
1303     if (renderContext_->GetAccessibilityFocus().value_or(false)) {
1304         auto paintWrapper = MakeRefPtr<PaintWrapper>(renderContext_, geometryNode_->Clone(), paintProperty_->Clone());
1305         paintWrapper->SetNodePaintMethod(MakeRefPtr<NodePaintMethod>());
1306         return paintWrapper;
1307     }
1308     return nullptr;
1309 }
1310 
PostTask(std::function<void ()> && task,TaskExecutor::TaskType taskType)1311 void FrameNode::PostTask(std::function<void()>&& task, TaskExecutor::TaskType taskType)
1312 {
1313     auto context = GetContext();
1314     CHECK_NULL_VOID(context);
1315     context->PostAsyncEvent(std::move(task), taskType);
1316 }
1317 
UpdateLayoutConstraint(const MeasureProperty & calcLayoutConstraint)1318 void FrameNode::UpdateLayoutConstraint(const MeasureProperty& calcLayoutConstraint)
1319 {
1320     layoutProperty_->UpdateCalcLayoutProperty(calcLayoutConstraint);
1321 }
1322 
RebuildRenderContextTree()1323 void FrameNode::RebuildRenderContextTree()
1324 {
1325     if (!needSyncRenderTree_) {
1326         return;
1327     }
1328     frameChildren_.clear();
1329     std::list<RefPtr<FrameNode>> children;
1330     // generate full children list, including disappear children.
1331     GenerateOneDepthVisibleFrameWithTransition(children);
1332     if (overlayNode_) {
1333         children.push_back(overlayNode_);
1334     }
1335     for (const auto& child : children) {
1336         frameChildren_.emplace(child);
1337     }
1338     renderContext_->RebuildFrame(this, children);
1339     pattern_->OnRebuildFrame();
1340     needSyncRenderTree_ = false;
1341 }
1342 
MarkModifyDone()1343 void FrameNode::MarkModifyDone()
1344 {
1345     pattern_->OnModifyDone();
1346     if (!isRestoreInfoUsed_) {
1347         isRestoreInfoUsed_ = true;
1348         auto pipeline = PipelineContext::GetCurrentContext();
1349         int32_t restoreId = GetRestoreId();
1350         if (pipeline && restoreId >= 0) {
1351             // store distribute node
1352             pipeline->StoreNode(restoreId, AceType::WeakClaim(this));
1353             // restore distribute node info
1354             std::string restoreInfo;
1355             if (pipeline->GetRestoreInfo(restoreId, restoreInfo)) {
1356                 pattern_->OnRestoreInfo(restoreInfo);
1357             }
1358         }
1359     }
1360     eventHub_->MarkModifyDone();
1361     renderContext_->OnModifyDone();
1362 }
1363 
OnMountToParentDone()1364 void FrameNode::OnMountToParentDone()
1365 {
1366     pattern_->OnMountToParentDone();
1367 }
1368 
FlushUpdateAndMarkDirty()1369 void FrameNode::FlushUpdateAndMarkDirty()
1370 {
1371     MarkDirtyNode();
1372 }
1373 
MarkDirtyNode(PropertyChangeFlag extraFlag,bool childExpansiveAndMark)1374 void FrameNode::MarkDirtyNode(PropertyChangeFlag extraFlag, bool childExpansiveAndMark)
1375 {
1376     if (CheckNeedMakePropertyDiff(extraFlag)) {
1377         if (isPropertyDiffMarked_) {
1378             return;
1379         }
1380         auto context = GetContext();
1381         CHECK_NULL_VOID(context);
1382         context->AddDirtyPropertyNode(Claim(this));
1383         isPropertyDiffMarked_ = true;
1384         return;
1385     }
1386     MarkDirtyNode(IsMeasureBoundary(), IsRenderBoundary(), extraFlag, childExpansiveAndMark);
1387 }
1388 
GetAncestorNodeOfFrame(bool checkBoundary) const1389 RefPtr<FrameNode> FrameNode::GetAncestorNodeOfFrame(bool checkBoundary) const
1390 {
1391     if (checkBoundary && IsWindowBoundary()) {
1392         return nullptr;
1393     }
1394     auto parent = GetParent();
1395     while (parent) {
1396         if (InstanceOf<FrameNode>(parent)) {
1397             return DynamicCast<FrameNode>(parent);
1398         }
1399         parent = parent->GetParent();
1400     }
1401     return nullptr;
1402 }
1403 
GetPageNode()1404 RefPtr<FrameNode> FrameNode::GetPageNode()
1405 {
1406     if (GetTag() == "page") {
1407         return Claim(this);
1408     }
1409     auto parent = GetParent();
1410     while (parent && parent->GetTag() != "page") {
1411         parent = parent->GetParent();
1412     }
1413     return AceType::DynamicCast<FrameNode>(parent);
1414 }
1415 
NotifyFillRequestSuccess(RefPtr<PageNodeInfoWrap> nodeWrap,AceAutoFillType autoFillType)1416 void FrameNode::NotifyFillRequestSuccess(RefPtr<PageNodeInfoWrap> nodeWrap, AceAutoFillType autoFillType)
1417 {
1418     if (pattern_) {
1419         pattern_->NotifyFillRequestSuccess(nodeWrap, autoFillType);
1420     }
1421 }
1422 
NotifyFillRequestFailed(int32_t errCode)1423 void FrameNode::NotifyFillRequestFailed(int32_t errCode)
1424 {
1425     if (pattern_) {
1426         pattern_->NotifyFillRequestFailed(errCode);
1427     }
1428 }
1429 
MarkNeedRenderOnly()1430 void FrameNode::MarkNeedRenderOnly()
1431 {
1432     MarkNeedRender(IsRenderBoundary());
1433 }
1434 
MarkNeedRender(bool isRenderBoundary)1435 void FrameNode::MarkNeedRender(bool isRenderBoundary)
1436 {
1437     auto context = GetContext();
1438     CHECK_NULL_VOID(context);
1439     // If it has dirtyLayoutBox, need to mark dirty after layout done.
1440     paintProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_RENDER);
1441     if (isRenderDirtyMarked_ || isLayoutDirtyMarked_) {
1442         return;
1443     }
1444     isRenderDirtyMarked_ = true;
1445     if (isRenderBoundary) {
1446         context->AddDirtyRenderNode(Claim(this));
1447         return;
1448     }
1449     auto parent = GetAncestorNodeOfFrame();
1450     if (parent) {
1451         parent->MarkDirtyNode(PROPERTY_UPDATE_RENDER_BY_CHILD_REQUEST);
1452     }
1453 }
1454 
MarkDirtyNode(bool isMeasureBoundary,bool isRenderBoundary,PropertyChangeFlag extraFlag,bool childExpansiveAndMark)1455 void FrameNode::MarkDirtyNode(
1456     bool isMeasureBoundary, bool isRenderBoundary, PropertyChangeFlag extraFlag, bool childExpansiveAndMark)
1457 {
1458     if (CheckNeedRender(extraFlag)) {
1459         paintProperty_->UpdatePropertyChangeFlag(extraFlag);
1460     }
1461     layoutProperty_->UpdatePropertyChangeFlag(extraFlag);
1462     paintProperty_->UpdatePropertyChangeFlag(extraFlag);
1463     auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
1464     auto paintFlag = paintProperty_->GetPropertyChangeFlag();
1465     if (CheckNoChanged(layoutFlag | paintFlag)) {
1466         return;
1467     }
1468     auto context = GetContext();
1469     CHECK_NULL_VOID(context);
1470 
1471     if (CheckNeedRequestMeasureAndLayout(layoutFlag)) {
1472         auto&& opts = GetLayoutProperty()->GetSafeAreaExpandOpts();
1473         auto selfExpansiveToMark = opts && opts->ExpansiveToMark();
1474         if ((!isMeasureBoundary && IsNeedRequestParentMeasure()) || selfExpansiveToMark) {
1475             bool parentStopMark = false;
1476             auto parent = GetAncestorNodeOfFrame();
1477             if (parent) {
1478                 auto parentPattern = parent->GetPattern();
1479                 parentStopMark = parentPattern && parentPattern->StopExpandMark();
1480             }
1481             // case 1: child not expand and mark, but self expand, need to check if parent stop expand mark
1482             // case 2: child and self not expand, regular mark parent
1483             // case 3: child expand and mark, need to check parent stop expand
1484             bool needMarkParent =
1485                 !childExpansiveAndMark || ((childExpansiveAndMark || selfExpansiveToMark) && !parentStopMark);
1486             if (needMarkParent && parent) {
1487                 parent->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1488                 return;
1489             }
1490         }
1491         if (isLayoutDirtyMarked_) {
1492             return;
1493         }
1494         isLayoutDirtyMarked_ = true;
1495         context->AddDirtyLayoutNode(Claim(this));
1496         return;
1497     }
1498     layoutProperty_->CleanDirty();
1499     MarkNeedRender(isRenderBoundary);
1500 }
1501 
IsNeedRequestParentMeasure() const1502 bool FrameNode::IsNeedRequestParentMeasure() const
1503 {
1504     auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
1505     if (layoutFlag == PROPERTY_UPDATE_BY_CHILD_REQUEST) {
1506         const auto& calcLayoutConstraint = layoutProperty_->GetCalcLayoutConstraint();
1507         if (calcLayoutConstraint && calcLayoutConstraint->selfIdealSize &&
1508             calcLayoutConstraint->selfIdealSize->IsValid()) {
1509             return false;
1510         }
1511     }
1512     return CheckNeedRequestParentMeasure(layoutFlag);
1513 }
1514 
OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & visibleList)1515 void FrameNode::OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& visibleList)
1516 {
1517     if (isActive_ && IsVisible()) {
1518         visibleList.emplace_back(Claim(this));
1519     }
1520 }
1521 
OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>> & allList)1522 void FrameNode::OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>>& allList)
1523 {
1524     allList.emplace_back(Claim(this));
1525 }
1526 
OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>> & visibleList)1527 void FrameNode::OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>>& visibleList)
1528 {
1529     auto context = GetRenderContext();
1530     CHECK_NULL_VOID(context);
1531     // skip if 1.not active or 2.not visible and has no transition out animation.
1532     if (!isActive_ || (!IsVisible() && !context->HasTransitionOutAnimation())) {
1533         return;
1534     }
1535     visibleList.emplace_back(Claim(this));
1536 }
1537 
IsMeasureBoundary()1538 bool FrameNode::IsMeasureBoundary()
1539 {
1540     return isMeasureBoundary_ || pattern_->IsMeasureBoundary();
1541 }
1542 
IsRenderBoundary()1543 bool FrameNode::IsRenderBoundary()
1544 {
1545     return pattern_->IsRenderBoundary();
1546 }
1547 
GetPattern() const1548 const RefPtr<Pattern>& FrameNode::GetPattern() const
1549 {
1550     return pattern_;
1551 }
1552 
IsAtomicNode() const1553 bool FrameNode::IsAtomicNode() const
1554 {
1555     return pattern_->IsAtomicNode();
1556 }
1557 
GetHitTestMode() const1558 HitTestMode FrameNode::GetHitTestMode() const
1559 {
1560     auto gestureHub = eventHub_->GetGestureEventHub();
1561     return gestureHub ? gestureHub->GetHitTestMode() : HitTestMode::HTMDEFAULT;
1562 }
1563 
SetHitTestMode(HitTestMode mode)1564 void FrameNode::SetHitTestMode(HitTestMode mode)
1565 {
1566     auto gestureHub = eventHub_->GetOrCreateGestureEventHub();
1567     CHECK_NULL_VOID(gestureHub);
1568     gestureHub->SetHitTestMode(mode);
1569 }
1570 
GetTouchable() const1571 bool FrameNode::GetTouchable() const
1572 {
1573     auto gestureHub = eventHub_->GetGestureEventHub();
1574     return gestureHub ? gestureHub->GetTouchable() : true;
1575 }
1576 
GetMonopolizeEvents() const1577 bool FrameNode::GetMonopolizeEvents() const
1578 {
1579     auto gestureHub = eventHub_->GetGestureEventHub();
1580     return gestureHub ? gestureHub->GetMonopolizeEvents() : false;
1581 }
1582 
GetPaintRectWithTransform() const1583 RectF FrameNode::GetPaintRectWithTransform() const
1584 {
1585     return renderContext_->GetPaintRectWithTransform();
1586 }
1587 
GetTransformScale() const1588 VectorF FrameNode::GetTransformScale() const
1589 {
1590     return renderContext_->GetTransformScaleValue({ 1.0f, 1.0f });
1591 }
1592 
IsOutOfTouchTestRegion(const PointF & parentRevertPoint,int32_t sourceType)1593 bool FrameNode::IsOutOfTouchTestRegion(const PointF& parentRevertPoint, int32_t sourceType)
1594 {
1595     bool isInChildRegion = false;
1596     auto paintRect = renderContext_->GetPaintRectWithoutTransform();
1597     auto responseRegionList = GetResponseRegionList(paintRect, sourceType);
1598     auto renderContext = GetRenderContext();
1599     CHECK_NULL_RETURN(renderContext, false);
1600 
1601     auto revertPoint = parentRevertPoint;
1602     renderContext->GetPointWithRevert(revertPoint);
1603     auto subRevertPoint = revertPoint - paintRect.GetOffset();
1604     auto clip = renderContext->GetClipEdge().value_or(false);
1605     if (!InResponseRegionList(revertPoint, responseRegionList) || !GetTouchable()) {
1606         if (clip) {
1607             LOGD("TouchTest: frameNode use clip, point is out of region in %{public}s", GetTag().c_str());
1608             return true;
1609         }
1610         for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
1611             const auto& child = iter->Upgrade();
1612             if (child && !child->IsOutOfTouchTestRegion(subRevertPoint, sourceType)) {
1613                 LOGD("TouchTest: point is out of region in %{public}s, but is in child region", GetTag().c_str());
1614                 isInChildRegion = true;
1615                 break;
1616             }
1617         }
1618         if (!isInChildRegion) {
1619             LOGD("TouchTest: point is out of region in %{public}s", GetTag().c_str());
1620             return true;
1621         }
1622     }
1623     return false;
1624 }
1625 
AddJudgeToTargetComponent(RefPtr<TargetComponent> & targetComponent)1626 void FrameNode::AddJudgeToTargetComponent(RefPtr<TargetComponent>& targetComponent)
1627 {
1628     auto gestureHub = eventHub_->GetGestureEventHub();
1629     if (gestureHub) {
1630         auto callback = gestureHub->GetOnGestureJudgeBeginCallback();
1631         if (callback) {
1632             targetComponent->SetOnGestureJudgeBegin(std::move(callback));
1633         }
1634         auto callbackNative = gestureHub->GetOnGestureJudgeNativeBeginCallback();
1635         if (callbackNative) {
1636             targetComponent->SetOnGestureJudgeNativeBegin(std::move(callbackNative));
1637         }
1638     }
1639 }
1640 
TouchTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,TouchRestrict & touchRestrict,TouchTestResult & result,int32_t touchId,bool isDispatch)1641 HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& parentLocalPoint,
1642     const PointF& parentRevertPoint, TouchRestrict& touchRestrict, TouchTestResult& result, int32_t touchId,
1643     bool isDispatch)
1644 {
1645     if (!isActive_ || !eventHub_->IsEnabled() || bypass_) {
1646         if (SystemProperties::GetDebugEnabled()) {
1647             LOGI("%{public}s is inActive, need't do touch test", GetTag().c_str());
1648         }
1649         return HitTestResult::OUT_OF_REGION;
1650     }
1651     auto& translateIds = NGGestureRecognizer::GetGlobalTransIds();
1652     auto& translateCfg = NGGestureRecognizer::GetGlobalTransCfg();
1653     auto paintRect = renderContext_->GetPaintRectWithTransform();
1654     auto origRect = renderContext_->GetPaintRectWithoutTransform();
1655     auto localMat = renderContext_->GetLocalTransformMatrix();
1656     auto param = renderContext_->GetTrans();
1657     localMat_ = localMat;
1658     if (param.empty()) {
1659         translateCfg[GetId()] = { .id = GetId(), .localMat = localMat };
1660     } else {
1661         translateCfg[GetId()] = { param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7],
1662             param[8], GetId(), localMat };
1663     }
1664 
1665     if (GetInspectorId().has_value() && GetInspectorId()->find("SCBScreen-Temp") != std::string::npos &&
1666         static_cast<int>(translateCfg[GetId()].degree) != 0) {
1667         translateCfg[GetId()].degree = 0.0;
1668         translateCfg[GetId()].localMat = Matrix4();
1669     }
1670     int32_t parentId = -1;
1671     auto parent = GetAncestorNodeOfFrame();
1672     if (parent) {
1673         AncestorNodeInfo ancestorNodeInfo { parent->GetId() };
1674         translateIds[GetId()] = ancestorNodeInfo;
1675         parentId = parent->GetId();
1676     }
1677 
1678     auto responseRegionList = GetResponseRegionList(origRect, static_cast<int32_t>(touchRestrict.sourceType));
1679     if (SystemProperties::GetDebugEnabled()) {
1680         LOGI("TouchTest: point is %{public}s in %{public}s, depth: %{public}d", parentRevertPoint.ToString().c_str(),
1681             GetTag().c_str(), GetDepth());
1682         for (const auto& rect : responseRegionList) {
1683             LOGI("TouchTest: responseRegionList is %{public}s, point is %{public}s", rect.ToString().c_str(),
1684                 parentRevertPoint.ToString().c_str());
1685         }
1686     }
1687     {
1688         ACE_DEBUG_SCOPED_TRACE("FrameNode::IsOutOfTouchTestRegion");
1689         bool isOutOfRegion = IsOutOfTouchTestRegion(parentRevertPoint, static_cast<int32_t>(touchRestrict.sourceType));
1690         AddFrameNodeSnapshot(!isOutOfRegion, parentId, responseRegionList);
1691         if ((!isDispatch) && isOutOfRegion) {
1692             return HitTestResult::OUT_OF_REGION;
1693         }
1694     }
1695 
1696     RefPtr<TargetComponent> targetComponent;
1697     if (targetComponent_.Upgrade()) {
1698         targetComponent = targetComponent_.Upgrade();
1699     } else {
1700         targetComponent = MakeRefPtr<TargetComponent>();
1701         targetComponent_ = targetComponent;
1702     }
1703     targetComponent->SetNode(WeakClaim(this));
1704     AddJudgeToTargetComponent(targetComponent);
1705 
1706     HitTestResult testResult = HitTestResult::OUT_OF_REGION;
1707     bool preventBubbling = false;
1708     // Child nodes are repackaged into gesture groups (parallel gesture groups, exclusive gesture groups, etc.)
1709     // based on the gesture attributes set by the current parent node (high and low priority, parallel gestures,
1710     // etc.), the newComingTargets is the template object to collect child nodes gesture and used by gestureHub to
1711     // pack gesture group.
1712     TouchTestResult newComingTargets;
1713     auto tmp = parentLocalPoint - paintRect.GetOffset();
1714     auto preLocation = tmp;
1715     renderContext_->GetPointWithTransform(tmp);
1716     const auto localPoint = tmp;
1717     auto localTransformOffset = preLocation - localPoint;
1718 
1719     auto revertPoint = parentRevertPoint;
1720     renderContext_->GetPointWithRevert(revertPoint);
1721     auto subRevertPoint = revertPoint - origRect.GetOffset();
1722     bool consumed = false;
1723 
1724     std::vector<TouchTestInfo> touchInfos;
1725     CollectTouchInfos(globalPoint, subRevertPoint, touchInfos);
1726     TouchResult touchRes = GetOnChildTouchTestRet(touchInfos);
1727     if ((touchRes.strategy != TouchTestStrategy::DEFAULT) && touchRes.id.empty()) {
1728         TAG_LOGW(AceLogTag::ACE_UIEVENT, "onChildTouchTest result is: id = %{public}s, strategy = %{public}d.",
1729             touchRes.id.c_str(), static_cast<int32_t>(touchRes.strategy));
1730         touchRes.strategy = TouchTestStrategy::DEFAULT;
1731     }
1732 
1733     auto childNode = GetDispatchFrameNode(touchRes);
1734     if (childNode != nullptr) {
1735         TAG_LOGD(AceLogTag::ACE_UIEVENT, "%{public}s do TouchTest, parameter isDispatch is true.",
1736             childNode->GetInspectorId()->c_str());
1737         auto hitResult = childNode->TouchTest(
1738             globalPoint, localPoint, subRevertPoint, touchRestrict, newComingTargets, touchId, true);
1739         if (touchRes.strategy == TouchTestStrategy::FORWARD ||
1740             touchRes.strategy == TouchTestStrategy::FORWARD_COMPETITION) {
1741             touchRestrict.childTouchTestList.emplace_back(touchRes.id);
1742         }
1743         if (hitResult == HitTestResult::STOP_BUBBLING) {
1744             preventBubbling = true;
1745             consumed = true;
1746         }
1747 
1748         if (hitResult == HitTestResult::BUBBLING) {
1749             consumed = true;
1750         }
1751     }
1752 
1753     for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
1754         if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
1755             break;
1756         }
1757         if (touchRes.strategy == TouchTestStrategy::FORWARD) {
1758             break;
1759         }
1760 
1761         const auto& child = iter->Upgrade();
1762         if (!child) {
1763             continue;
1764         }
1765 
1766         std::string id;
1767         if (child->GetInspectorId().has_value()) {
1768             id = child->GetInspectorId().value();
1769         }
1770         if (touchRes.strategy == TouchTestStrategy::FORWARD_COMPETITION && touchRes.id == id) {
1771             continue;
1772         }
1773 
1774         auto childHitResult =
1775             child->TouchTest(globalPoint, localPoint, subRevertPoint, touchRestrict, newComingTargets, touchId);
1776         if (childHitResult == HitTestResult::STOP_BUBBLING) {
1777             preventBubbling = true;
1778             consumed = true;
1779             if ((child->GetHitTestMode() == HitTestMode::HTMBLOCK) ||
1780                 (child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
1781                 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
1782                 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && IsExclusiveEventForChild())) {
1783                 break;
1784             }
1785         }
1786 
1787         // In normal process, the node block the brother node.
1788         if (childHitResult == HitTestResult::BUBBLING &&
1789             ((child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
1790                 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
1791                 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && IsExclusiveEventForChild()))) {
1792             consumed = true;
1793             break;
1794         }
1795     }
1796 
1797     // first update HitTestResult by children status.
1798     if (consumed) {
1799         testResult = preventBubbling ? HitTestResult::STOP_BUBBLING : HitTestResult::BUBBLING;
1800         consumed = false;
1801     } else if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
1802         testResult = HitTestResult::STOP_BUBBLING;
1803     }
1804 
1805     if (!preventBubbling && (GetHitTestMode() != HitTestMode::HTMNONE) &&
1806         (isDispatch || (InResponseRegionList(revertPoint, responseRegionList)))) {
1807         pattern_->OnTouchTestHit(touchRestrict.hitTestType);
1808         consumed = true;
1809         if (touchRestrict.hitTestType == SourceType::TOUCH) {
1810             auto gestureHub = eventHub_->GetGestureEventHub();
1811             if (gestureHub) {
1812                 TouchTestResult finalResult;
1813                 const auto coordinateOffset = globalPoint - localPoint - localTransformOffset;
1814                 preventBubbling = gestureHub->ProcessTouchTestHit(coordinateOffset, touchRestrict, newComingTargets,
1815                     finalResult, touchId, localPoint, targetComponent);
1816                 newComingTargets.swap(finalResult);
1817             }
1818         } else if (touchRestrict.hitTestType == SourceType::MOUSE) {
1819             auto mouseHub = eventHub_->GetInputEventHub();
1820             if (mouseHub) {
1821                 const auto coordinateOffset = globalPoint - localPoint;
1822                 preventBubbling = mouseHub->ProcessMouseTestHit(coordinateOffset, newComingTargets);
1823             }
1824         }
1825     }
1826 
1827     result.splice(result.end(), std::move(newComingTargets));
1828     if (touchRestrict.hitTestType == SourceType::TOUCH) {
1829         // combine into exclusive recognizer group.
1830         auto gestureHub = eventHub_->GetGestureEventHub();
1831         if (gestureHub) {
1832             gestureHub->CombineIntoExclusiveRecognizer(globalPoint, localPoint, result, touchId);
1833         }
1834     }
1835 
1836     // consumed by children and return result.
1837     if (!consumed) {
1838         return testResult;
1839     }
1840 
1841     if (testResult == HitTestResult::OUT_OF_REGION) {
1842         // consume only by self.
1843         if (preventBubbling) {
1844             return HitTestResult::STOP_BUBBLING;
1845         }
1846         return (GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ? HitTestResult::SELF_TRANSPARENT
1847                                                                       : HitTestResult::BUBBLING;
1848     }
1849     // consume by self and children.
1850     return testResult;
1851 }
1852 
GetResponseRegionList(const RectF & rect,int32_t sourceType)1853 std::vector<RectF> FrameNode::GetResponseRegionList(const RectF& rect, int32_t sourceType)
1854 {
1855     std::vector<RectF> responseRegionList;
1856     auto gestureHub = eventHub_->GetGestureEventHub();
1857     if (!gestureHub) {
1858         responseRegionList.emplace_back(rect);
1859         return responseRegionList;
1860     }
1861     auto scaleProperty = ScaleProperty::CreateScaleProperty();
1862     bool isMouseEvent = (static_cast<SourceType>(sourceType) == SourceType::MOUSE);
1863     if (isMouseEvent) {
1864         if (gestureHub->GetResponseRegion().empty() && (gestureHub->GetMouseResponseRegion().empty())) {
1865             responseRegionList.emplace_back(rect);
1866             return responseRegionList;
1867         }
1868     } else {
1869         if (gestureHub->GetResponseRegion().empty()) {
1870             responseRegionList.emplace_back(rect);
1871             return responseRegionList;
1872         }
1873     }
1874 
1875     if (isMouseEvent && (!gestureHub->GetMouseResponseRegion().empty())) {
1876         for (const auto& region : gestureHub->GetMouseResponseRegion()) {
1877             auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
1878             auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
1879             auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
1880             auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
1881             RectF mouseRegion(rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(),
1882                 height.value());
1883             responseRegionList.emplace_back(mouseRegion);
1884         }
1885         return responseRegionList;
1886     }
1887     for (const auto& region : gestureHub->GetResponseRegion()) {
1888         auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
1889         auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
1890         auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
1891         auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
1892         RectF responseRegion(
1893             rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(), height.value());
1894         responseRegionList.emplace_back(responseRegion);
1895     }
1896     return responseRegionList;
1897 }
1898 
GetResponseRegionListForRecognizer(int32_t sourceType)1899 std::vector<RectF> FrameNode::GetResponseRegionListForRecognizer(int32_t sourceType)
1900 {
1901     auto paintRect = renderContext_->GetPaintRectWithoutTransform();
1902     auto responseRegionList = GetResponseRegionList(paintRect, sourceType);
1903     return responseRegionList;
1904 }
1905 
InResponseRegionList(const PointF & parentLocalPoint,const std::vector<RectF> & responseRegionList) const1906 bool FrameNode::InResponseRegionList(const PointF& parentLocalPoint, const std::vector<RectF>& responseRegionList) const
1907 {
1908     for (const auto& rect : responseRegionList) {
1909         if (rect.IsInRegion(parentLocalPoint)) {
1910             return true;
1911         }
1912     }
1913     return false;
1914 }
1915 
MouseTest(const PointF & globalPoint,const PointF & parentLocalPoint,MouseTestResult & onMouseResult,MouseTestResult & onHoverResult,RefPtr<FrameNode> & hoverNode)1916 HitTestResult FrameNode::MouseTest(const PointF& globalPoint, const PointF& parentLocalPoint,
1917     MouseTestResult& onMouseResult, MouseTestResult& onHoverResult, RefPtr<FrameNode>& hoverNode)
1918 {
1919     // unuseable function. do nothing.
1920     return HitTestResult::BUBBLING;
1921 }
1922 
AxisTest(const PointF & globalPoint,const PointF & parentLocalPoint,AxisTestResult & onAxisResult)1923 HitTestResult FrameNode::AxisTest(
1924     const PointF& globalPoint, const PointF& parentLocalPoint, AxisTestResult& onAxisResult)
1925 {
1926     const auto& rect = renderContext_->GetPaintRectWithTransform();
1927     // TODO: disableTouchEvent || disabled_ need handle
1928 
1929     // TODO: Region need change to RectList
1930     if (!rect.IsInRegion(parentLocalPoint)) {
1931         return HitTestResult::OUT_OF_REGION;
1932     }
1933 
1934     bool preventBubbling = false;
1935 
1936     const auto localPoint = parentLocalPoint - rect.GetOffset();
1937     const auto& children = GetChildren();
1938     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
1939         auto& child = *iter;
1940         auto childHitResult = child->AxisTest(globalPoint, localPoint, onAxisResult);
1941         if (childHitResult == HitTestResult::STOP_BUBBLING) {
1942             preventBubbling = true;
1943         }
1944         // In normal process, the node block the brother node.
1945         if (childHitResult == HitTestResult::BUBBLING) {
1946             // TODO: add hit test mode judge.
1947             break;
1948         }
1949     }
1950 
1951     AxisTestResult axisResult;
1952     bool isPrevent = false;
1953     auto inputHub = eventHub_->GetInputEventHub();
1954     if (inputHub) {
1955         const auto coordinateOffset = globalPoint - localPoint;
1956         isPrevent = inputHub->ProcessAxisTestHit(coordinateOffset, axisResult);
1957     }
1958 
1959     if (!preventBubbling) {
1960         preventBubbling = isPrevent;
1961         onAxisResult.splice(onAxisResult.end(), std::move(axisResult));
1962     }
1963     if (preventBubbling) {
1964         return HitTestResult::STOP_BUBBLING;
1965     }
1966     return HitTestResult::BUBBLING;
1967 }
1968 
AnimateHoverEffect(bool isHovered) const1969 void FrameNode::AnimateHoverEffect(bool isHovered) const
1970 {
1971     auto renderContext = GetRenderContext();
1972     if (!renderContext) {
1973         return;
1974     }
1975     HoverEffectType animationType = HoverEffectType::UNKNOWN;
1976     auto inputEventHub = eventHub_->GetInputEventHub();
1977     if (inputEventHub) {
1978         animationType = inputEventHub->GetHoverEffect();
1979         if (animationType == HoverEffectType::UNKNOWN || animationType == HoverEffectType::AUTO) {
1980             animationType = inputEventHub->GetHoverEffectAuto();
1981         }
1982     }
1983     if (animationType == HoverEffectType::SCALE) {
1984         renderContext->AnimateHoverEffectScale(isHovered);
1985     } else if (animationType == HoverEffectType::BOARD) {
1986         renderContext->AnimateHoverEffectBoard(isHovered);
1987     }
1988 }
1989 
GetOrCreateFocusHub() const1990 RefPtr<FocusHub> FrameNode::GetOrCreateFocusHub() const
1991 {
1992     if (!pattern_) {
1993         return eventHub_->GetOrCreateFocusHub();
1994     }
1995     auto focusPattern = pattern_->GetFocusPattern();
1996     return eventHub_->GetOrCreateFocusHub(focusPattern);
1997 }
1998 
OnWindowShow()1999 void FrameNode::OnWindowShow()
2000 {
2001     pattern_->OnWindowShow();
2002 }
2003 
OnWindowHide()2004 void FrameNode::OnWindowHide()
2005 {
2006     pattern_->OnWindowHide();
2007 }
2008 
OnWindowFocused()2009 void FrameNode::OnWindowFocused()
2010 {
2011     pattern_->OnWindowFocused();
2012 }
2013 
OnWindowUnfocused()2014 void FrameNode::OnWindowUnfocused()
2015 {
2016     pattern_->OnWindowUnfocused();
2017 }
2018 
ContextPositionConvertToPX(const RefPtr<RenderContext> & context,const SizeF & percentReference) const2019 std::pair<float, float> FrameNode::ContextPositionConvertToPX(
2020     const RefPtr<RenderContext>& context, const SizeF& percentReference) const
2021 {
2022     std::pair<float, float> position;
2023     CHECK_NULL_RETURN(context, position);
2024     auto scaleProperty = ScaleProperty::CreateScaleProperty();
2025     position.first =
2026         ConvertToPx(context->GetPositionProperty()->GetPosition()->GetX(), scaleProperty, percentReference.Width())
2027             .value_or(0.0);
2028     position.second =
2029         ConvertToPx(context->GetPositionProperty()->GetPosition()->GetY(), scaleProperty, percentReference.Height())
2030             .value_or(0.0);
2031     return position;
2032 }
2033 
OnPixelRoundFinish(const SizeF & pixelGridRoundSize)2034 void FrameNode::OnPixelRoundFinish(const SizeF& pixelGridRoundSize)
2035 {
2036     CHECK_NULL_VOID(pattern_);
2037     pattern_->OnPixelRoundFinish(pixelGridRoundSize);
2038 }
2039 
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)2040 void FrameNode::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
2041 {
2042     pattern_->OnWindowSizeChanged(width, height, type);
2043 }
2044 
2045 /* @deprecated  This func will be deleted, please use GetTransformRelativeOffset() instead. */
GetOffsetRelativeToWindow() const2046 OffsetF FrameNode::GetOffsetRelativeToWindow() const
2047 {
2048     auto offset = geometryNode_->GetFrameOffset();
2049     auto parent = GetAncestorNodeOfFrame(true);
2050     if (renderContext_ && renderContext_->GetPositionProperty()) {
2051         if (renderContext_->GetPositionProperty()->HasPosition()) {
2052             auto renderPosition =
2053                 ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
2054             offset.SetX(static_cast<float>(renderPosition.first));
2055             offset.SetY(static_cast<float>(renderPosition.second));
2056         }
2057     }
2058     while (parent) {
2059         auto parentRenderContext = parent->GetRenderContext();
2060         if (parentRenderContext && parentRenderContext->GetPositionProperty()) {
2061             if (parentRenderContext->GetPositionProperty()->HasPosition()) {
2062                 auto parentLayoutProperty = parent->GetLayoutProperty();
2063                 CHECK_NULL_RETURN(parentLayoutProperty, offset);
2064                 auto parentRenderContextPosition = ContextPositionConvertToPX(
2065                     parentRenderContext, parentLayoutProperty->GetLayoutConstraint()->percentReference);
2066                 offset.AddX(static_cast<float>(parentRenderContextPosition.first));
2067                 offset.AddY(static_cast<float>(parentRenderContextPosition.second));
2068                 parent = parent->GetAncestorNodeOfFrame(true);
2069                 continue;
2070             }
2071         }
2072 
2073         offset += parent->geometryNode_->GetFrameOffset();
2074         parent = parent->GetAncestorNodeOfFrame(true);
2075     }
2076 
2077     return offset;
2078 }
2079 
GetTransformRectRelativeToWindow() const2080 RectF FrameNode::GetTransformRectRelativeToWindow() const
2081 {
2082     auto context = GetRenderContext();
2083     CHECK_NULL_RETURN(context, RectF());
2084     RectF rect = context->GetPaintRectWithTransform();
2085     auto offset = rect.GetOffset();
2086     auto parent = GetAncestorNodeOfFrame(true);
2087     while (parent) {
2088         auto parentRenderContext = parent->GetRenderContext();
2089         CHECK_NULL_RETURN(parentRenderContext, rect);
2090         auto parentScale = parentRenderContext->GetTransformScale();
2091         if (parentScale) {
2092             auto oldSize = rect.GetSize();
2093             auto newSize = SizeF(oldSize.Width() * parentScale.value().x, oldSize.Height() * parentScale.value().y);
2094             rect.SetSize(newSize);
2095 
2096             offset = OffsetF(offset.GetX() * parentScale.value().x, offset.GetY() * parentScale.value().y);
2097         }
2098 
2099         offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
2100 
2101         parent = parent->GetAncestorNodeOfFrame(true);
2102     }
2103     rect.SetOffset(offset);
2104     return rect;
2105 }
2106 
GetTransformRelativeOffset() const2107 OffsetF FrameNode::GetTransformRelativeOffset() const
2108 {
2109     auto context = GetRenderContext();
2110     CHECK_NULL_RETURN(context, OffsetF());
2111     auto offset = context->GetPaintRectWithTransform().GetOffset();
2112     auto parent = GetAncestorNodeOfFrame(true);
2113 
2114     while (parent) {
2115         auto parentRenderContext = parent->GetRenderContext();
2116         offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
2117         parent = parent->GetAncestorNodeOfFrame(true);
2118     }
2119 
2120     return offset;
2121 }
2122 
GetPaintRectOffset(bool excludeSelf) const2123 OffsetF FrameNode::GetPaintRectOffset(bool excludeSelf) const
2124 {
2125     auto context = GetRenderContext();
2126     CHECK_NULL_RETURN(context, OffsetF());
2127     OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithTransform().GetOffset();
2128     auto parent = GetAncestorNodeOfFrame();
2129     while (parent) {
2130         auto renderContext = parent->GetRenderContext();
2131         CHECK_NULL_RETURN(renderContext, OffsetF());
2132         offset += renderContext->GetPaintRectWithTransform().GetOffset();
2133         parent = parent->GetAncestorNodeOfFrame();
2134     }
2135     return offset;
2136 }
2137 
GetPaintRectCenter() const2138 OffsetF FrameNode::GetPaintRectCenter() const
2139 {
2140     auto context = GetRenderContext();
2141     CHECK_NULL_RETURN(context, OffsetF());
2142     auto trans = context->GetPaintRectWithTransform();
2143     auto offset = trans.GetOffset();
2144     auto center = offset + OffsetF(trans.Width() / 2.0f, trans.Height() / 2.0f);
2145     auto parent = GetAncestorNodeOfFrame();
2146     while (parent) {
2147         auto renderContext = parent->GetRenderContext();
2148         CHECK_NULL_RETURN(renderContext, OffsetF());
2149         auto scale = renderContext->GetTransformScale();
2150         if (scale) {
2151             center.SetX(center.GetX() * scale.value().x);
2152             center.SetY(center.GetY() * scale.value().y);
2153         }
2154         center += renderContext->GetPaintRectWithTransform().GetOffset();
2155         parent = parent->GetAncestorNodeOfFrame();
2156     }
2157     return center;
2158 }
2159 
GetParentGlobalOffsetDuringLayout() const2160 OffsetF FrameNode::GetParentGlobalOffsetDuringLayout() const
2161 {
2162     OffsetF offset {};
2163     auto parent = GetAncestorNodeOfFrame();
2164     while (parent) {
2165         offset += parent->geometryNode_->GetFrameOffset();
2166         parent = parent->GetAncestorNodeOfFrame();
2167     }
2168     return offset;
2169 }
2170 
GetPaintRectGlobalOffsetWithTranslate(bool excludeSelf) const2171 std::pair<OffsetF, bool> FrameNode::GetPaintRectGlobalOffsetWithTranslate(bool excludeSelf) const
2172 {
2173     bool error = false;
2174     auto context = GetRenderContext();
2175     CHECK_NULL_RETURN(context, std::make_pair(OffsetF(), error));
2176     OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithTranslate().first.GetOffset();
2177     auto parent = GetAncestorNodeOfFrame();
2178     while (parent) {
2179         auto renderContext = parent->GetRenderContext();
2180         CHECK_NULL_RETURN(renderContext, std::make_pair(OffsetF(), error));
2181         auto [rect, err] = renderContext->GetPaintRectWithTranslate();
2182         error = error || err;
2183         CHECK_NULL_RETURN(rect.IsValid(), std::make_pair(offset + parent->GetPaintRectOffset(), error));
2184         offset += rect.GetOffset();
2185         parent = parent->GetAncestorNodeOfFrame();
2186     }
2187     return std::make_pair(offset, error);
2188 }
2189 
GetPaintRectOffsetToPage() const2190 OffsetF FrameNode::GetPaintRectOffsetToPage() const
2191 {
2192     auto context = GetRenderContext();
2193     CHECK_NULL_RETURN(context, OffsetF());
2194     OffsetF offset = context->GetPaintRectWithTransform().GetOffset();
2195     auto parent = GetAncestorNodeOfFrame();
2196     while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
2197         auto renderContext = parent->GetRenderContext();
2198         CHECK_NULL_RETURN(renderContext, OffsetF());
2199         offset += renderContext->GetPaintRectWithTransform().GetOffset();
2200         parent = parent->GetAncestorNodeOfFrame();
2201     }
2202     return (parent && parent->GetTag() == V2::PAGE_ETS_TAG) ? offset : OffsetF();
2203 }
2204 
GetViewPort() const2205 std::optional<RectF> FrameNode::GetViewPort() const
2206 {
2207     if (viewPort_.has_value()) {
2208         return viewPort_;
2209     }
2210     auto parent = GetAncestorNodeOfFrame();
2211     while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
2212         auto parentViewPort = parent->GetSelfViewPort();
2213         if (parentViewPort.has_value()) {
2214             return parentViewPort;
2215         }
2216         parent = parent->GetAncestorNodeOfFrame();
2217     }
2218     return std::nullopt;
2219 }
2220 
OnNotifyMemoryLevel(int32_t level)2221 void FrameNode::OnNotifyMemoryLevel(int32_t level)
2222 {
2223     pattern_->OnNotifyMemoryLevel(level);
2224 }
2225 
GetAllDepthChildrenCount()2226 int32_t FrameNode::GetAllDepthChildrenCount()
2227 {
2228     int32_t result = 0;
2229     std::list<RefPtr<FrameNode>> children;
2230     children.emplace_back(Claim(this));
2231     while (!children.empty()) {
2232         auto& node = children.front();
2233         if (!node->IsInternal()) {
2234             result++;
2235             node->GenerateOneDepthVisibleFrame(children);
2236         }
2237         children.pop_front();
2238     }
2239     return result;
2240 }
2241 
OnAccessibilityEvent(AccessibilityEventType eventType,WindowsContentChangeTypes windowsContentChangeType) const2242 void FrameNode::OnAccessibilityEvent(
2243     AccessibilityEventType eventType, WindowsContentChangeTypes windowsContentChangeType) const
2244 {
2245     if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
2246         AccessibilityEvent event;
2247         event.type = eventType;
2248         event.windowContentChangeTypes = windowsContentChangeType;
2249         event.nodeId = GetAccessibilityId();
2250         auto pipeline = PipelineContext::GetCurrentContext();
2251         CHECK_NULL_VOID(pipeline);
2252         pipeline->SendEventToAccessibility(event);
2253     }
2254 }
2255 
OnAccessibilityEvent(AccessibilityEventType eventType,std::string beforeText,std::string latestContent) const2256 void FrameNode::OnAccessibilityEvent(
2257     AccessibilityEventType eventType, std::string beforeText, std::string latestContent) const
2258 {
2259     if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
2260         AccessibilityEvent event;
2261         event.type = eventType;
2262         event.nodeId = GetAccessibilityId();
2263         event.beforeText = beforeText;
2264         event.latestContent = latestContent;
2265         auto pipeline = PipelineContext::GetCurrentContext();
2266         CHECK_NULL_VOID(pipeline);
2267         pipeline->SendEventToAccessibility(event);
2268     }
2269 }
2270 
MarkRemoving()2271 bool FrameNode::MarkRemoving()
2272 {
2273     bool pendingRemove = false;
2274     if (!layoutProperty_ || !geometryNode_) {
2275         return pendingRemove;
2276     }
2277 
2278     isRemoving_ = true;
2279 
2280     const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
2281     if (geometryTransition != nullptr) {
2282         geometryTransition->Build(WeakClaim(this), false);
2283         pendingRemove = true;
2284     }
2285 
2286     const auto& children = GetChildren();
2287     for (const auto& child : children) {
2288         pendingRemove = child->MarkRemoving() || pendingRemove;
2289     }
2290     return pendingRemove;
2291 }
2292 
AddHotZoneRect(const DimensionRect & hotZoneRect) const2293 void FrameNode::AddHotZoneRect(const DimensionRect& hotZoneRect) const
2294 {
2295     auto gestureHub = GetOrCreateGestureEventHub();
2296     gestureHub->AddResponseRect(hotZoneRect);
2297 }
2298 
RemoveLastHotZoneRect() const2299 void FrameNode::RemoveLastHotZoneRect() const
2300 {
2301     auto gestureHub = GetOrCreateGestureEventHub();
2302     gestureHub->RemoveLastResponseRect();
2303 }
2304 
OnRemoveFromParent(bool allowTransition)2305 bool FrameNode::OnRemoveFromParent(bool allowTransition)
2306 {
2307     // kick out transition animation if needed, wont re-entry if already detached.
2308     DetachFromMainTree(!allowTransition);
2309     auto context = GetRenderContext();
2310     CHECK_NULL_RETURN(context, false);
2311     if (!allowTransition || RemoveImmediately()) {
2312         // directly remove, reset parent and depth
2313         ResetParent();
2314         return true;
2315     }
2316     // delayed remove, will move self into disappearing children
2317     return false;
2318 }
2319 
FindChildByPosition(float x,float y)2320 RefPtr<FrameNode> FrameNode::FindChildByPosition(float x, float y)
2321 {
2322     std::map<int32_t, RefPtr<FrameNode>> hitFrameNodes;
2323     std::list<RefPtr<FrameNode>> children;
2324     GenerateOneDepthAllFrame(children);
2325     for (const auto& child : children) {
2326         auto geometryNode = child->GetGeometryNode();
2327         if (!geometryNode) {
2328             continue;
2329         }
2330 
2331         auto globalFrameRect = geometryNode->GetFrameRect();
2332         globalFrameRect.SetOffset(child->GetOffsetRelativeToWindow());
2333 
2334         if (globalFrameRect.IsInRegion(PointF(x, y))) {
2335             hitFrameNodes.insert(std::make_pair(child->GetDepth(), child));
2336         }
2337     }
2338 
2339     if (hitFrameNodes.empty()) {
2340         return nullptr;
2341     }
2342 
2343     return hitFrameNodes.rbegin()->second;
2344 }
2345 
GetAnimatablePropertyFloat(const std::string & propertyName) const2346 RefPtr<NodeAnimatablePropertyBase> FrameNode::GetAnimatablePropertyFloat(const std::string& propertyName) const
2347 {
2348     auto iter = nodeAnimatablePropertyMap_.find(propertyName);
2349     if (iter == nodeAnimatablePropertyMap_.end()) {
2350         return nullptr;
2351     }
2352     return iter->second;
2353 }
2354 
FindChildByName(const RefPtr<FrameNode> & parentNode,const std::string & nodeName)2355 RefPtr<FrameNode> FrameNode::FindChildByName(const RefPtr<FrameNode>& parentNode, const std::string& nodeName)
2356 {
2357     CHECK_NULL_RETURN(parentNode, nullptr);
2358     const auto& children = parentNode->GetChildren();
2359     for (const auto& child : children) {
2360         auto childFrameNode = AceType::DynamicCast<FrameNode>(child);
2361         if (childFrameNode && childFrameNode->GetInspectorId().value_or("") == nodeName) {
2362             return childFrameNode;
2363         }
2364         auto childFindResult = FindChildByName(childFrameNode, nodeName);
2365         if (childFindResult) {
2366             return childFindResult;
2367         }
2368     }
2369     return nullptr;
2370 }
2371 
CreateAnimatablePropertyFloat(const std::string & propertyName,float value,const std::function<void (float)> & onCallbackEvent,const PropertyUnit & propertyType)2372 void FrameNode::CreateAnimatablePropertyFloat(
2373     const std::string& propertyName, float value, const std::function<void(float)>& onCallbackEvent,
2374     const PropertyUnit& propertyType)
2375 {
2376     auto context = GetRenderContext();
2377     CHECK_NULL_VOID(context);
2378     auto iter = nodeAnimatablePropertyMap_.find(propertyName);
2379     if (iter != nodeAnimatablePropertyMap_.end()) {
2380         return;
2381     }
2382     auto property = AceType::MakeRefPtr<NodeAnimatablePropertyFloat>(value, std::move(onCallbackEvent));
2383     context->AttachNodeAnimatableProperty(property);
2384     if (propertyType == PropertyUnit::PIXEL_POSITION) {
2385         property->SetPropertyUnit(propertyType);
2386     }
2387     nodeAnimatablePropertyMap_.emplace(propertyName, property);
2388 }
2389 
DeleteAnimatablePropertyFloat(const std::string & propertyName)2390 void FrameNode::DeleteAnimatablePropertyFloat(const std::string& propertyName)
2391 {
2392     auto context = GetRenderContext();
2393     CHECK_NULL_VOID(context);
2394     RefPtr<NodeAnimatablePropertyBase> propertyRef = GetAnimatablePropertyFloat(propertyName);
2395     if (propertyRef) {
2396         context->DetachNodeAnimatableProperty(propertyRef);
2397         nodeAnimatablePropertyMap_.erase(propertyName);
2398     }
2399 }
2400 
UpdateAnimatablePropertyFloat(const std::string & propertyName,float value)2401 void FrameNode::UpdateAnimatablePropertyFloat(const std::string& propertyName, float value)
2402 {
2403     auto iter = nodeAnimatablePropertyMap_.find(propertyName);
2404     if (iter == nodeAnimatablePropertyMap_.end()) {
2405         return;
2406     }
2407     auto property = AceType::DynamicCast<NodeAnimatablePropertyFloat>(iter->second);
2408     CHECK_NULL_VOID(property);
2409     property->Set(value);
2410 }
2411 
CreateAnimatableArithmeticProperty(const std::string & propertyName,RefPtr<CustomAnimatableArithmetic> & value,std::function<void (const RefPtr<CustomAnimatableArithmetic> &)> & onCallbackEvent)2412 void FrameNode::CreateAnimatableArithmeticProperty(const std::string& propertyName,
2413     RefPtr<CustomAnimatableArithmetic>& value,
2414     std::function<void(const RefPtr<CustomAnimatableArithmetic>&)>& onCallbackEvent)
2415 {
2416     auto context = GetRenderContext();
2417     CHECK_NULL_VOID(context);
2418     auto iter = nodeAnimatablePropertyMap_.find(propertyName);
2419     if (iter != nodeAnimatablePropertyMap_.end()) {
2420         return;
2421     }
2422     auto property = AceType::MakeRefPtr<NodeAnimatableArithmeticProperty>(value, std::move(onCallbackEvent));
2423     context->AttachNodeAnimatableProperty(property);
2424     nodeAnimatablePropertyMap_.emplace(propertyName, property);
2425 }
2426 
UpdateAnimatableArithmeticProperty(const std::string & propertyName,RefPtr<CustomAnimatableArithmetic> & value)2427 void FrameNode::UpdateAnimatableArithmeticProperty(
2428     const std::string& propertyName, RefPtr<CustomAnimatableArithmetic>& value)
2429 {
2430     auto iter = nodeAnimatablePropertyMap_.find(propertyName);
2431     if (iter == nodeAnimatablePropertyMap_.end()) {
2432         return;
2433     }
2434     auto property = AceType::DynamicCast<NodeAnimatableArithmeticProperty>(iter->second);
2435     CHECK_NULL_VOID(property);
2436     property->Set(value);
2437 }
2438 
ProvideRestoreInfo()2439 std::string FrameNode::ProvideRestoreInfo()
2440 {
2441     return pattern_->ProvideRestoreInfo();
2442 }
2443 
RemoveImmediately() const2444 bool FrameNode::RemoveImmediately() const
2445 {
2446     auto context = GetRenderContext();
2447     CHECK_NULL_RETURN(context, true);
2448     // has transition out animation, need to wait for animation end
2449     return !context->HasTransitionOutAnimation();
2450 }
2451 
GetNodesById(const std::unordered_set<int32_t> & set)2452 std::vector<RefPtr<FrameNode>> FrameNode::GetNodesById(const std::unordered_set<int32_t>& set)
2453 {
2454     std::vector<RefPtr<FrameNode>> nodes;
2455     for (auto nodeId : set) {
2456         auto uiNode = ElementRegister::GetInstance()->GetUINodeById(nodeId);
2457         if (!uiNode) {
2458             continue;
2459         }
2460         auto frameNode = DynamicCast<FrameNode>(uiNode);
2461         if (frameNode) {
2462             nodes.emplace_back(frameNode);
2463         }
2464     }
2465     return nodes;
2466 }
2467 
GetPreviewScaleVal() const2468 double FrameNode::GetPreviewScaleVal() const
2469 {
2470     double scale = 1.0;
2471     auto maxWidth = GridSystemManager::GetInstance().GetMaxWidthWithColumnType(GridColumnType::DRAG_PANEL);
2472     auto geometryNode = GetGeometryNode();
2473     CHECK_NULL_RETURN(geometryNode, scale);
2474     auto width = geometryNode->GetFrameRect().Width();
2475     if (GetTag() != V2::WEB_ETS_TAG && width != 0 && width > maxWidth &&
2476         previewOption_.mode != DragPreviewMode::DISABLE_SCALE) {
2477         scale = maxWidth / width;
2478     }
2479     return scale;
2480 }
2481 
IsPreviewNeedScale() const2482 bool FrameNode::IsPreviewNeedScale() const
2483 {
2484     return GetPreviewScaleVal() < 1.0f;
2485 }
2486 
GetNodeExpectedRate()2487 int32_t FrameNode::GetNodeExpectedRate()
2488 {
2489     if (sceneRateMap_.empty()) {
2490         return 0;
2491     }
2492     auto iter = std::max_element(
2493         sceneRateMap_.begin(), sceneRateMap_.end(), [](auto a, auto b) { return a.second < b.second; });
2494     return iter->second;
2495 }
2496 
AddFRCSceneInfo(const std::string & scene,float speed,SceneStatus status)2497 void FrameNode::AddFRCSceneInfo(const std::string& scene, float speed, SceneStatus status)
2498 {
2499     if (SystemProperties::GetDebugEnabled()) {
2500         const std::string sceneStatusStrs[] = {"START", "RUNNING", "END"};
2501         LOGI("%{public}s  AddFRCSceneInfo scene:%{public}s   speed:%{public}f  status:%{public}s", GetTag().c_str(),
2502             scene.c_str(), std::abs(speed), sceneStatusStrs[static_cast<int32_t>(status)].c_str());
2503     }
2504 
2505     auto renderContext = GetRenderContext();
2506     CHECK_NULL_VOID(renderContext);
2507     auto pipelineContext = GetContext();
2508     CHECK_NULL_VOID(pipelineContext);
2509     auto frameRateManager = pipelineContext->GetFrameRateManager();
2510     CHECK_NULL_VOID(frameRateManager);
2511 
2512     auto expectedRate = renderContext->CalcExpectedFrameRate(scene, std::abs(speed));
2513     auto nodeId = GetId();
2514     auto iter = sceneRateMap_.find(scene);
2515     switch (status) {
2516         case SceneStatus::START: {
2517             if (iter == sceneRateMap_.end()) {
2518                 if (sceneRateMap_.empty()) {
2519                     frameRateManager->AddNodeRate(nodeId);
2520                 }
2521                 sceneRateMap_.emplace(scene, expectedRate);
2522                 frameRateManager->UpdateNodeRate(nodeId, GetNodeExpectedRate());
2523             }
2524             return;
2525         }
2526         case SceneStatus::RUNNING: {
2527             if (iter != sceneRateMap_.end() && iter->second != expectedRate) {
2528                 iter->second = expectedRate;
2529                 auto nodeExpectedRate = GetNodeExpectedRate();
2530                 frameRateManager->UpdateNodeRate(nodeId, nodeExpectedRate);
2531             }
2532             return;
2533         }
2534         case SceneStatus::END: {
2535             if (iter != sceneRateMap_.end()) {
2536                 sceneRateMap_.erase(iter);
2537                 if (sceneRateMap_.empty()) {
2538                     frameRateManager->RemoveNodeRate(nodeId);
2539                 } else {
2540                     auto nodeExpectedRate = GetNodeExpectedRate();
2541                     frameRateManager->UpdateNodeRate(nodeId, nodeExpectedRate);
2542                 }
2543             }
2544             return;
2545         }
2546         default:
2547             return;
2548     }
2549 }
2550 
CheckSecurityComponentStatus(std::vector<RectF> & rect)2551 void FrameNode::CheckSecurityComponentStatus(std::vector<RectF>& rect)
2552 {
2553     auto paintRect = GetTransformRectRelativeToWindow();
2554     if (IsSecurityComponent()) {
2555         bypass_ = CheckRectIntersect(paintRect, rect);
2556     }
2557     for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
2558         const auto& child = iter->Upgrade();
2559         if (child) {
2560             child->CheckSecurityComponentStatus(rect);
2561         }
2562     }
2563     rect.push_back(paintRect);
2564 }
2565 
CheckRectIntersect(const RectF & dest,std::vector<RectF> & origin)2566 bool FrameNode::CheckRectIntersect(const RectF& dest, std::vector<RectF>& origin)
2567 {
2568     for (auto originRect : origin) {
2569         if (originRect.IsInnerIntersectWith(dest)) {
2570             return true;
2571         }
2572     }
2573     return false;
2574 }
2575 
HaveSecurityComponent()2576 bool FrameNode::HaveSecurityComponent()
2577 {
2578     if (IsSecurityComponent()) {
2579         return true;
2580     }
2581     for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
2582         const auto& child = iter->Upgrade();
2583         if (child && child->HaveSecurityComponent()) {
2584             return true;
2585         }
2586     }
2587     return false;
2588 }
2589 
IsSecurityComponent()2590 bool FrameNode::IsSecurityComponent()
2591 {
2592     return GetTag() == V2::LOCATION_BUTTON_ETS_TAG || GetTag() == V2::PASTE_BUTTON_ETS_TAG ||
2593            GetTag() == V2::SAVE_BUTTON_ETS_TAG;
2594 }
2595 
GetPercentSensitive()2596 void FrameNode::GetPercentSensitive()
2597 {
2598     auto res = layoutProperty_->GetPercentSensitive();
2599     if (res.first) {
2600         if (layoutAlgorithm_) {
2601             layoutAlgorithm_->SetPercentWidth(true);
2602         }
2603     }
2604     if (res.second) {
2605         if (layoutAlgorithm_) {
2606             layoutAlgorithm_->SetPercentHeight(true);
2607         }
2608     }
2609 }
2610 
UpdatePercentSensitive()2611 void FrameNode::UpdatePercentSensitive()
2612 {
2613     bool percentHeight = layoutAlgorithm_ ? layoutAlgorithm_->GetPercentHeight() : true;
2614     bool percentWidth = layoutAlgorithm_ ? layoutAlgorithm_->GetPercentWidth() : true;
2615     auto res = layoutProperty_->UpdatePercentSensitive(percentHeight, percentWidth);
2616     if (res.first) {
2617         auto parent = GetAncestorNodeOfFrame();
2618         if (parent && parent->layoutAlgorithm_) {
2619             parent->layoutAlgorithm_->SetPercentWidth(true);
2620         }
2621     }
2622     if (res.second) {
2623         auto parent = GetAncestorNodeOfFrame();
2624         if (parent && parent->layoutAlgorithm_) {
2625             parent->layoutAlgorithm_->SetPercentHeight(true);
2626         }
2627     }
2628 }
2629 
2630 // This will call child and self measure process.
Measure(const std::optional<LayoutConstraintF> & parentConstraint)2631 void FrameNode::Measure(const std::optional<LayoutConstraintF>& parentConstraint)
2632 {
2633     ACE_LAYOUT_SCOPED_TRACE("Measure[%s][self:%d][parent:%d][key:%s]", GetTag().c_str(),
2634         GetId(), GetParent() ? GetParent()->GetId() : 0, GetInspectorIdValue("").c_str());
2635 
2636     if (SelfOrParentExpansive() && needRestoreSafeArea_) {
2637         RestoreGeoState();
2638         needRestoreSafeArea_ = false;
2639     }
2640     isLayoutComplete_ = false;
2641     if (!oldGeometryNode_) {
2642         oldGeometryNode_ = geometryNode_->Clone();
2643     }
2644     pattern_->BeforeCreateLayoutWrapper();
2645     GetLayoutAlgorithm(true);
2646 
2647     if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
2648         layoutAlgorithm_->SetSkipMeasure();
2649         layoutAlgorithm_->SetSkipLayout();
2650         geometryNode_->SetFrameSize(SizeF());
2651         isLayoutDirtyMarked_ = false;
2652         return;
2653     }
2654     if (!isActive_) {
2655         layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
2656     }
2657 
2658     if (layoutAlgorithm_->SkipMeasure()) {
2659         isLayoutDirtyMarked_ = false;
2660         return;
2661     }
2662 
2663     const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
2664     if (geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this))) {
2665         geometryTransition->WillLayout(Claim(this));
2666     }
2667     auto preConstraint = layoutProperty_->GetLayoutConstraint();
2668     auto contentConstraint = layoutProperty_->GetContentLayoutConstraint();
2669     layoutProperty_->BuildGridProperty(Claim(this));
2670 
2671     if (parentConstraint) {
2672         ApplyConstraint(*parentConstraint);
2673     } else {
2674         CreateRootConstraint();
2675     }
2676 
2677     layoutProperty_->UpdateContentConstraint();
2678     geometryNode_->UpdateMargin(layoutProperty_->CreateMargin());
2679     geometryNode_->UpdatePaddingWithBorder(layoutProperty_->CreatePaddingAndBorder());
2680 
2681     isConstraintNotChanged_ = layoutProperty_->ConstraintEqual(preConstraint, contentConstraint);
2682 
2683     isLayoutDirtyMarked_ = false;
2684 
2685     if (isConstraintNotChanged_) {
2686         if (!CheckNeedForceMeasureAndLayout()) {
2687             ACE_SCOPED_TRACE("SkipMeasure");
2688             layoutAlgorithm_->SetSkipMeasure();
2689             return;
2690         }
2691     }
2692 
2693     auto size = layoutAlgorithm_->MeasureContent(layoutProperty_->CreateContentConstraint(), this);
2694     if (size.has_value()) {
2695         geometryNode_->SetContentSize(size.value());
2696     }
2697     GetPercentSensitive();
2698     layoutAlgorithm_->Measure(this);
2699     if (overlayNode_) {
2700         overlayNode_->Measure(layoutProperty_->CreateChildConstraint());
2701     }
2702     UpdatePercentSensitive();
2703     // check aspect radio.
2704     if (pattern_ && pattern_->IsNeedAdjustByAspectRatio()) {
2705         const auto& magicItemProperty = layoutProperty_->GetMagicItemProperty();
2706         auto aspectRatio = magicItemProperty.GetAspectRatioValue();
2707         // Adjust by aspect ratio, firstly pick height based on width. It means that when width, height and
2708         // aspectRatio are all set, the height is not used.
2709         auto width = geometryNode_->GetFrameSize().Width();
2710         auto height = width / aspectRatio;
2711         geometryNode_->SetFrameSize(SizeF({ width, height }));
2712     }
2713 
2714     layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
2715 }
2716 
2717 // Called to perform layout children.
Layout()2718 void FrameNode::Layout()
2719 {
2720     ACE_LAYOUT_SCOPED_TRACE("Layout[%s][self:%d][parent:%d][key:%s]", GetTag().c_str(),
2721         GetId(), GetParent() ? GetParent()->GetId() : 0, GetInspectorIdValue("").c_str());
2722     if (SelfOrParentExpansive()) {
2723         if (IsRootMeasureNode() && !needRestoreSafeArea_ && SelfExpansive()) {
2724             GetGeometryNode()->RestoreCache();
2725         } else if (needRestoreSafeArea_) {
2726             // if safeArea not restored in measure because of constraint not changed and so on,
2727             // restore this node
2728             RestoreGeoState();
2729             needRestoreSafeArea_ = false;
2730         }
2731     }
2732     int64_t time = GetSysTimestamp();
2733     OffsetNodeToSafeArea();
2734     const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
2735     if (geometryTransition != nullptr) {
2736         if (!IsRootMeasureNode() && geometryTransition->IsNodeInAndActive(Claim(this))) {
2737             SetSkipSyncGeometryNode();
2738         }
2739     }
2740     if (CheckNeedLayout(layoutProperty_->GetPropertyChangeFlag())) {
2741         if (!layoutProperty_->GetLayoutConstraint()) {
2742             const auto& parentLayoutConstraint = geometryNode_->GetParentLayoutConstraint();
2743             if (parentLayoutConstraint) {
2744                 layoutProperty_->UpdateLayoutConstraint(parentLayoutConstraint.value());
2745             } else {
2746                 LayoutConstraintF layoutConstraint;
2747                 layoutConstraint.percentReference.SetWidth(PipelineContext::GetCurrentRootWidth());
2748                 layoutConstraint.percentReference.SetHeight(PipelineContext::GetCurrentRootHeight());
2749                 layoutProperty_->UpdateLayoutConstraint(layoutConstraint);
2750             }
2751             layoutProperty_->UpdateContentConstraint();
2752         }
2753         GetLayoutAlgorithm()->Layout(this);
2754         if (overlayNode_) {
2755             LayoutOverlay();
2756         }
2757         time = GetSysTimestamp() - time;
2758         AddNodeFlexLayouts();
2759         AddNodeLayoutTime(time);
2760     } else {
2761         GetLayoutAlgorithm()->SetSkipLayout();
2762     }
2763 
2764     auto pipeline = PipelineContext::GetCurrentContext();
2765     CHECK_NULL_VOID(pipeline);
2766     bool isFocusOnPage = pipeline->CheckPageFocus();
2767     AvoidKeyboard(isFocusOnPage);
2768     bool needSyncRsNode = false;
2769     bool willSyncGeoProperties = OnLayoutFinish(needSyncRsNode);
2770     // skip wrapping task if node will not sync
2771     CHECK_NULL_VOID(willSyncGeoProperties);
2772     auto task = [weak = WeakClaim(this), needSync = needSyncRsNode]() {
2773         auto frameNode = weak.Upgrade();
2774         CHECK_NULL_VOID(frameNode);
2775         frameNode->SyncGeometryNode(needSync);
2776     };
2777     pipeline->AddSyncGeometryNodeTask(task);
2778     // if a node has geo transition but not the root node, add task only but not flush
2779     // or add to expand list, self node will be added to expand list in next layout
2780     if (geometryTransition != nullptr && !IsRootMeasureNode()) {
2781         return;
2782     }
2783     if (SelfOrParentExpansive()) {
2784         auto pipeline = PipelineContext::GetCurrentContext();
2785         CHECK_NULL_VOID(pipeline);
2786         auto safeAreaManager = pipeline->GetSafeAreaManager();
2787         CHECK_NULL_VOID(safeAreaManager);
2788         safeAreaManager->AddNeedExpandNode(GetHostNode());
2789     }
2790     if (geometryTransition != nullptr) {
2791         pipeline->FlushSyncGeometryNodeTasks();
2792     }
2793 }
2794 
SelfExpansive()2795 bool FrameNode::SelfExpansive()
2796 {
2797     auto&& opts = GetLayoutProperty()->GetSafeAreaExpandOpts();
2798     return opts && opts->Expansive();
2799 }
2800 
ParentExpansive()2801 bool FrameNode::ParentExpansive()
2802 {
2803     auto parent = GetAncestorNodeOfFrame();
2804     CHECK_NULL_RETURN(parent, false);
2805     auto parentLayoutProperty = parent->GetLayoutProperty();
2806     CHECK_NULL_RETURN(parentLayoutProperty, false);
2807     auto&& parentOpts = parentLayoutProperty->GetSafeAreaExpandOpts();
2808     return parentOpts && parentOpts->Expansive();
2809 }
2810 
SelfOrParentExpansive()2811 bool FrameNode::SelfOrParentExpansive()
2812 {
2813     return SelfExpansive() || ParentExpansive();
2814 }
2815 
OnLayoutFinish(bool & needSyncRsNode)2816 bool FrameNode::OnLayoutFinish(bool& needSyncRsNode)
2817 {
2818     const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
2819     bool hasTransition = geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this));
2820     if (!isActive_ && !hasTransition) {
2821         layoutAlgorithm_.Reset();
2822         return false;
2823     }
2824     if (needSkipSyncGeometryNode_ && (!geometryTransition || !geometryTransition->IsNodeInAndActive(Claim(this)))) {
2825         layoutAlgorithm_.Reset();
2826         return false;
2827     }
2828     // update layout size.
2829     bool frameSizeChange = true;
2830     bool frameOffsetChange = true;
2831     bool contentSizeChange = true;
2832     bool contentOffsetChange = true;
2833     if (oldGeometryNode_) {
2834         frameSizeChange = geometryNode_->GetFrameSize() != oldGeometryNode_->GetFrameSize();
2835         frameOffsetChange = geometryNode_->GetFrameOffset() != oldGeometryNode_->GetFrameOffset();
2836         contentSizeChange = geometryNode_->GetContentSize() != oldGeometryNode_->GetContentSize();
2837         contentOffsetChange = geometryNode_->GetContentOffset() != oldGeometryNode_->GetContentOffset();
2838         oldGeometryNode_.Reset();
2839     }
2840 
2841     // clean layout flag.
2842     layoutProperty_->CleanDirty();
2843     needSyncRsNode = frameSizeChange || frameOffsetChange ||
2844                      (pattern_->GetContextParam().has_value() && contentSizeChange) || HasPositionProp() ||
2845                      SelfOrParentExpansive();
2846     if (hasTransition) {
2847         geometryTransition->DidLayout(Claim(this));
2848         if (geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
2849             isLayoutDirtyMarked_ = true;
2850         }
2851         needSyncRsNode = false;
2852     }
2853     renderContext_->SavePaintRect(true, layoutProperty_->GetPixelRound());
2854     renderContext_->SyncPartialRsProperties();
2855     DirtySwapConfig config { frameSizeChange, frameOffsetChange, contentSizeChange, contentOffsetChange };
2856     // check if need to paint content.
2857     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(layoutAlgorithm_);
2858     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
2859     config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure();
2860     config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
2861     if (!config.skipMeasure && !config.skipLayout && GetInspectorId()) {
2862         auto pipeline = PipelineContext::GetCurrentContext();
2863         CHECK_NULL_RETURN(pipeline, false);
2864         pipeline->OnLayoutCompleted(GetInspectorId()->c_str());
2865     }
2866     auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config);
2867     needRerender =
2868         needRerender || pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config.skipMeasure, config.skipLayout);
2869     if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
2870         MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
2871     }
2872     layoutAlgorithm_.Reset();
2873     return true;
2874 }
2875 
SyncGeometryNode(bool needSyncRsNode)2876 void FrameNode::SyncGeometryNode(bool needSyncRsNode)
2877 {
2878     ACE_LAYOUT_SCOPED_TRACE("SyncGeometryNode[%s][self:%d][parent:%d][key:%s]", GetTag().c_str(),
2879         GetId(), GetParent() ? GetParent()->GetId() : 0, GetInspectorIdValue("").c_str());
2880     // update border.
2881     if (layoutProperty_->GetBorderWidthProperty()) {
2882         if (!renderContext_->HasBorderColor()) {
2883             BorderColorProperty borderColorProperty;
2884             borderColorProperty.SetColor(Color::BLACK);
2885             renderContext_->UpdateBorderColor(borderColorProperty);
2886         }
2887         if (!renderContext_->HasBorderStyle()) {
2888             BorderStyleProperty borderStyleProperty;
2889             borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
2890             renderContext_->UpdateBorderStyle(borderStyleProperty);
2891         }
2892         if (layoutProperty_->GetLayoutConstraint().has_value()) {
2893             renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
2894                 ScaleProperty::CreateScaleProperty(),
2895                 layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
2896         } else {
2897             renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
2898                 ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
2899         }
2900     }
2901     if (needSyncRsNode) {
2902         isLayoutComplete_ = true;
2903         renderContext_->SyncGeometryProperties(RawPtr(geometryNode_), true, layoutProperty_->GetPixelRound());
2904     }
2905 
2906     // update background
2907     if (builderFunc_) {
2908         auto builderNode = builderFunc_();
2909         auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
2910             AceType::MakeRefPtr<LinearLayoutPattern>(true));
2911         if (builderNode) {
2912             builderNode->MountToParent(columnNode);
2913         }
2914         SetBackgroundLayoutConstraint(columnNode);
2915         renderContext_->CreateBackgroundPixelMap(columnNode);
2916         builderFunc_ = nullptr;
2917         backgroundNode_ = columnNode;
2918     }
2919 
2920     // update focus state
2921     auto focusHub = GetFocusHub();
2922     if (focusHub && focusHub->IsCurrentFocus()) {
2923         focusHub->ClearFocusState(false);
2924         focusHub->PaintFocusState(false);
2925     }
2926 
2927     // rebuild child render node.
2928     RebuildRenderContextTree();
2929 
2930     /* Adjust components' position which have been set grid properties */
2931     AdjustGridOffset();
2932 }
2933 
2934 
GetOrCreateChildByIndex(uint32_t index,bool addToRenderTree)2935 RefPtr<LayoutWrapper> FrameNode::GetOrCreateChildByIndex(uint32_t index, bool addToRenderTree)
2936 {
2937     auto child = frameProxy_->GetFrameNodeByIndex(index, true);
2938     if (child) {
2939         child->SetSkipSyncGeometryNode(SkipSyncGeometryNode());
2940         if (addToRenderTree) {
2941             child->SetActive(true);
2942         }
2943     }
2944     return child;
2945 }
2946 
GetChildByIndex(uint32_t index)2947 RefPtr<LayoutWrapper> FrameNode::GetChildByIndex(uint32_t index)
2948 {
2949     return frameProxy_->GetFrameNodeByIndex(index, false);
2950 }
2951 
GetAllChildrenWithBuild(bool addToRenderTree)2952 const std::list<RefPtr<LayoutWrapper>>& FrameNode::GetAllChildrenWithBuild(bool addToRenderTree)
2953 {
2954     const auto& children = frameProxy_->GetAllFrameChildren();
2955     {
2956         auto guard = frameProxy_->GetGuard();
2957         for (const auto& child : children) {
2958             if (addToRenderTree) {
2959                 child->SetActive(true);
2960             }
2961             child->SetSkipSyncGeometryNode(SkipSyncGeometryNode());
2962         }
2963     }
2964 
2965     return children;
2966 }
2967 
RemoveAllChildInRenderTree()2968 void FrameNode::RemoveAllChildInRenderTree()
2969 {
2970     frameProxy_->RemoveAllChildInRenderTree();
2971 }
2972 
SetActiveChildRange(int32_t start,int32_t end)2973 void FrameNode::SetActiveChildRange(int32_t start, int32_t end)
2974 {
2975     frameProxy_->SetActiveChildRange(start, end);
2976 }
2977 
RemoveChildInRenderTree(uint32_t index)2978 void FrameNode::RemoveChildInRenderTree(uint32_t index)
2979 {
2980     frameProxy_->RemoveChildInRenderTree(index);
2981 }
2982 
SkipMeasureContent() const2983 bool FrameNode::SkipMeasureContent() const
2984 {
2985     return layoutAlgorithm_->SkipMeasure();
2986 }
2987 
CheckNeedForceMeasureAndLayout()2988 bool FrameNode::CheckNeedForceMeasureAndLayout()
2989 {
2990     PropertyChangeFlag flag = layoutProperty_->GetPropertyChangeFlag();
2991     return CheckNeedMeasure(flag) || CheckNeedLayout(flag);
2992 }
2993 
GetOffsetInScreen()2994 OffsetF FrameNode::GetOffsetInScreen()
2995 {
2996     auto frameOffset = GetPaintRectOffset();
2997     auto pipelineContext = PipelineContext::GetCurrentContext();
2998     CHECK_NULL_RETURN(pipelineContext, OffsetF(0.0f, 0.0f));
2999     auto window = pipelineContext->GetWindow();
3000     CHECK_NULL_RETURN(window, OffsetF(0.0f, 0.0f));
3001     auto windowOffset = window->GetCurrentWindowRect().GetOffset();
3002     frameOffset += OffsetT<float> { windowOffset.GetX(), windowOffset.GetY() };
3003     return frameOffset;
3004 }
3005 
GetPixelMap()3006 RefPtr<PixelMap> FrameNode::GetPixelMap()
3007 {
3008     auto gestureHub = GetOrCreateGestureEventHub();
3009     CHECK_NULL_RETURN(gestureHub, nullptr);
3010     RefPtr<PixelMap> pixelMap = gestureHub->GetPixelMap();
3011     // if gesture already have pixel map return directly
3012     if (pixelMap) {
3013         return pixelMap;
3014     }
3015     CHECK_NULL_RETURN(renderContext_, nullptr);
3016     pixelMap = renderContext_->GetThumbnailPixelMap();
3017     gestureHub->SetPixelMap(pixelMap);
3018     return pixelMap;
3019 }
3020 
GetBaselineDistance() const3021 float FrameNode::GetBaselineDistance() const
3022 {
3023     const auto& children = frameProxy_->GetAllFrameChildren();
3024     if (children.empty()) {
3025         return geometryNode_->GetBaselineDistance();
3026     }
3027     float distance = 0.0;
3028     {
3029         auto guard = frameProxy_->GetGuard();
3030         for (const auto& child : children) {
3031             float childBaseline = child->GetBaselineDistance();
3032             distance = NearZero(distance) ? childBaseline : std::min(distance, childBaseline);
3033         }
3034     }
3035     return distance;
3036 }
3037 
MarkNeedSyncRenderTree(bool needRebuild)3038 void FrameNode::MarkNeedSyncRenderTree(bool needRebuild)
3039 {
3040     if (needRebuild) {
3041         frameProxy_->ResetChildren(true);
3042     }
3043     needSyncRenderTree_ = true;
3044 }
3045 
GetFrameChildByIndex(uint32_t index,bool needBuild)3046 RefPtr<UINode> FrameNode::GetFrameChildByIndex(uint32_t index, bool needBuild)
3047 {
3048     if (index != 0) {
3049         return nullptr;
3050     }
3051     return Claim(this);
3052 }
3053 
GetLayoutAlgorithm(bool needReset)3054 const RefPtr<LayoutAlgorithmWrapper>& FrameNode::GetLayoutAlgorithm(bool needReset)
3055 {
3056     if ((!layoutAlgorithm_ || (needReset && layoutAlgorithm_->IsExpire())) && pattern_) {
3057         layoutAlgorithm_ = MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm());
3058     }
3059     if (needReset) {
3060         layoutAlgorithm_->SetNeedMeasure();
3061     }
3062     return layoutAlgorithm_;
3063 }
3064 
SetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)3065 void FrameNode::SetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
3066 {
3067     frameProxy_->SetCacheCount(cacheCount, itemConstraint);
3068 }
3069 
LayoutOverlay()3070 void FrameNode::LayoutOverlay()
3071 {
3072     auto size = geometryNode_->GetFrameSize();
3073     auto align = Alignment::TOP_LEFT;
3074     Dimension offsetX, offsetY;
3075     auto childLayoutProperty = overlayNode_->GetLayoutProperty();
3076     childLayoutProperty->GetOverlayOffset(offsetX, offsetY);
3077     auto offset = OffsetF(offsetX.ConvertToPx(), offsetY.ConvertToPx());
3078     if (childLayoutProperty->GetPositionProperty()) {
3079         align = childLayoutProperty->GetPositionProperty()->GetAlignment().value_or(align);
3080     }
3081 
3082     auto childSize = overlayNode_->GetGeometryNode()->GetMarginFrameSize();
3083     auto translate = Alignment::GetAlignPosition(size, childSize, align) + offset;
3084     overlayNode_->GetGeometryNode()->SetMarginFrameOffset(translate);
3085     overlayNode_->Layout();
3086 }
3087 
DoRemoveChildInRenderTree(uint32_t index,bool isAll)3088 void FrameNode::DoRemoveChildInRenderTree(uint32_t index, bool isAll)
3089 {
3090     isActive_ = false;
3091     SetActive(false);
3092 }
3093 
DoSetActiveChildRange(int32_t start,int32_t end)3094 void FrameNode::DoSetActiveChildRange(int32_t start, int32_t end)
3095 {
3096     if (start <= end) {
3097         if (start > 0 || end < 0) {
3098             SetActive(false);
3099             SetJSViewActive(false);
3100         } else {
3101             SetJSViewActive(true);
3102         }
3103     } else {
3104         if (end < 0 && start > 0) {
3105             SetActive(false);
3106             SetJSViewActive(false);
3107         } else {
3108             SetJSViewActive(true);
3109         }
3110     }
3111 }
3112 
OnInspectorIdUpdate(const std::string & id)3113 void FrameNode::OnInspectorIdUpdate(const std::string& id)
3114 {
3115     RecordExposureIfNeed(id);
3116     auto parent = GetAncestorNodeOfFrame();
3117     CHECK_NULL_VOID(parent);
3118     if (parent->GetTag() == V2::RELATIVE_CONTAINER_ETS_TAG) {
3119         parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3120     }
3121 }
3122 
RecordExposureIfNeed(const std::string & inspectorId)3123 void FrameNode::RecordExposureIfNeed(const std::string& inspectorId)
3124 {
3125     if (exposureProcessor_) {
3126         return;
3127     }
3128     exposureProcessor_ = MakeRefPtr<Recorder::ExposureProcessor>(inspectorId);
3129     if (!exposureProcessor_->IsNeedRecord()) {
3130         return;
3131     }
3132     auto pipeline = PipelineContext::GetCurrentContext();
3133     CHECK_NULL_VOID(pipeline);
3134     auto callback = [weak = WeakClaim(RawPtr(exposureProcessor_))](bool visible, double ratio) {
3135         auto processor = weak.Upgrade();
3136         CHECK_NULL_VOID(processor);
3137         processor->OnVisibleChange(visible);
3138     };
3139     pipeline->AddVisibleAreaChangeNode(Claim(this), exposureProcessor_->GetRatio(), callback, false);
3140 }
3141 
AddFrameNodeSnapshot(bool isHit,int32_t parentId,std::vector<RectF> responseRegionList)3142 void FrameNode::AddFrameNodeSnapshot(bool isHit, int32_t parentId, std::vector<RectF> responseRegionList)
3143 {
3144     auto context = PipelineContext::GetCurrentContext();
3145     CHECK_NULL_VOID(context);
3146     auto eventMgr = context->GetEventManager();
3147     CHECK_NULL_VOID(eventMgr);
3148 
3149     FrameNodeSnapshot info = {
3150         .nodeId = GetId(),
3151         .parentNodeId = parentId,
3152         .tag = GetTag(),
3153         .comId = propInspectorId_.value_or(""),
3154         .monopolizeEvents = GetMonopolizeEvents(),
3155         .isHit = isHit,
3156         .hitTestMode = static_cast<int32_t>(GetHitTestMode()),
3157         .responseRegionList = responseRegionList
3158     };
3159     eventMgr->GetEventTreeRecord().AddFrameNodeSnapshot(std::move(info));
3160 }
3161 
GetUiExtensionId()3162 int32_t FrameNode::GetUiExtensionId()
3163 {
3164     if (pattern_) {
3165         return pattern_->GetUiExtensionId();
3166     }
3167     return -1;
3168 }
3169 
WrapExtensionAbilityId(int64_t extensionOffset,int64_t abilityId)3170 int64_t FrameNode::WrapExtensionAbilityId(int64_t extensionOffset, int64_t abilityId)
3171 {
3172     if (pattern_) {
3173         return pattern_->WrapExtensionAbilityId(extensionOffset, abilityId);
3174     }
3175     return -1;
3176 }
3177 
SearchExtensionElementInfoByAccessibilityIdNG(int64_t elementId,int32_t mode,int64_t offset,std::list<Accessibility::AccessibilityElementInfo> & output)3178 void FrameNode::SearchExtensionElementInfoByAccessibilityIdNG(int64_t elementId, int32_t mode,
3179     int64_t offset, std::list<Accessibility::AccessibilityElementInfo>& output)
3180 {
3181     if (pattern_) {
3182         pattern_->SearchExtensionElementInfoByAccessibilityId(elementId, mode, offset, output);
3183     }
3184 }
3185 
SearchElementInfosByTextNG(int64_t elementId,const std::string & text,int64_t offset,std::list<Accessibility::AccessibilityElementInfo> & output)3186 void FrameNode::SearchElementInfosByTextNG(int64_t elementId, const std::string& text,
3187     int64_t offset, std::list<Accessibility::AccessibilityElementInfo>& output)
3188 {
3189     if (pattern_) {
3190         pattern_->SearchElementInfosByText(elementId, text, offset, output);
3191     }
3192 }
3193 
FindFocusedExtensionElementInfoNG(int64_t elementId,int32_t focusType,int64_t offset,Accessibility::AccessibilityElementInfo & output)3194 void FrameNode::FindFocusedExtensionElementInfoNG(int64_t elementId, int32_t focusType,
3195     int64_t offset, Accessibility::AccessibilityElementInfo& output)
3196 {
3197     if (pattern_) {
3198         pattern_->FindFocusedElementInfo(elementId, focusType, offset, output);
3199     }
3200 }
3201 
FocusMoveSearchNG(int64_t elementId,int32_t direction,int64_t offset,Accessibility::AccessibilityElementInfo & output)3202 void FrameNode::FocusMoveSearchNG(int64_t elementId, int32_t direction,
3203     int64_t offset, Accessibility::AccessibilityElementInfo& output)
3204 {
3205     if (pattern_) {
3206         pattern_->FocusMoveSearch(elementId, direction, offset, output);
3207     }
3208 }
3209 
TransferExecuteAction(int64_t elementId,const std::map<std::string,std::string> & actionArguments,int32_t action,int64_t offset)3210 bool FrameNode::TransferExecuteAction(int64_t elementId, const std::map<std::string, std::string>& actionArguments,
3211     int32_t action, int64_t offset)
3212 {
3213     bool isExecuted = false;
3214     if (pattern_) {
3215         isExecuted = pattern_->TransferExecuteAction(elementId, actionArguments, action, offset);
3216     }
3217     return isExecuted;
3218 }
3219 
GetOnChildTouchTestRet(const std::vector<TouchTestInfo> & touchInfo)3220 TouchResult FrameNode::GetOnChildTouchTestRet(const std::vector<TouchTestInfo>& touchInfo)
3221 {
3222     TouchResult res;
3223     res.strategy = TouchTestStrategy::DEFAULT;
3224 
3225     auto func = GetOnTouchTestFunc();
3226     if (func == nullptr) {
3227         return res;
3228     }
3229     return func(touchInfo);
3230 }
3231 
GetOnTouchTestFunc()3232 OnChildTouchTestFunc FrameNode::GetOnTouchTestFunc()
3233 {
3234     auto gestureHub = eventHub_->GetGestureEventHub();
3235     if (gestureHub == nullptr) {
3236         return nullptr;
3237     }
3238     auto& func = gestureHub->GetOnTouchTestFunc();
3239     return func;
3240 }
3241 
CollectTouchInfos(const PointF & globalPoint,const PointF & parentRevertPoint,std::vector<TouchTestInfo> & touchInfos)3242 void FrameNode::CollectTouchInfos(
3243     const PointF& globalPoint, const PointF& parentRevertPoint, std::vector<TouchTestInfo>& touchInfos)
3244 {
3245     if (GetOnTouchTestFunc() == nullptr) {
3246         return;
3247     }
3248 
3249     for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
3250         const auto& child = iter->Upgrade();
3251         if (!child) {
3252             continue;
3253         }
3254 
3255         TouchTestInfo info;
3256         if (!child->GetInspectorId().has_value()) {
3257             continue;
3258         }
3259         info.id = child->GetInspectorId().value();
3260         info.windowPoint = globalPoint;
3261         info.currentCmpPoint = parentRevertPoint;
3262 
3263         auto renderContext = child->GetRenderContext();
3264         CHECK_NULL_VOID(renderContext);
3265         auto origRect = renderContext->GetPaintRectWithoutTransform();
3266         auto revertPoint = parentRevertPoint;
3267         renderContext->GetPointWithRevert(revertPoint);
3268         auto subRevertPoint = revertPoint - origRect.GetOffset();
3269         info.subCmpPoint = subRevertPoint;
3270 
3271         info.subRect = child->GetGeometryNode()->GetFrameRect();
3272 
3273         touchInfos.emplace_back(info);
3274     }
3275 }
3276 
GetDispatchFrameNode(const TouchResult & touchRes)3277 RefPtr<FrameNode> FrameNode::GetDispatchFrameNode(const TouchResult& touchRes)
3278 {
3279     if (touchRes.strategy != TouchTestStrategy::FORWARD_COMPETITION &&
3280         touchRes.strategy != TouchTestStrategy::FORWARD) {
3281         return nullptr;
3282     }
3283 
3284     for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
3285         const auto& child = iter->Upgrade();
3286         if (!child) {
3287             continue;
3288         }
3289         std::string id = child->GetInspectorId().value_or("");
3290         if ((!touchRes.id.empty()) && (touchRes.id == id)) {
3291             return child;
3292         }
3293     }
3294     return nullptr;
3295 }
3296 
CalculateCachedTransformRelativeOffset(uint64_t nanoTimestamp)3297 OffsetF FrameNode::CalculateCachedTransformRelativeOffset(uint64_t nanoTimestamp)
3298 {
3299     auto context = GetRenderContext();
3300     CHECK_NULL_RETURN(context, OffsetF());
3301     auto offset = context->GetPaintRectWithTransform().GetOffset();
3302 
3303     auto parent = GetAncestorNodeOfFrame(true);
3304     if (parent) {
3305         auto parentTimestampOffset = parent->GetCachedTransformRelativeOffset();
3306         if (parentTimestampOffset.first == nanoTimestamp) {
3307             auto result = offset + parentTimestampOffset.second;
3308             SetCachedTransformRelativeOffset({ nanoTimestamp, result });
3309             return result;
3310         } else {
3311             auto result = offset + parent->CalculateCachedTransformRelativeOffset(nanoTimestamp);
3312             SetCachedTransformRelativeOffset({ nanoTimestamp, result });
3313             return result;
3314         }
3315     } else {
3316         SetCachedTransformRelativeOffset({ nanoTimestamp, offset });
3317         return offset;
3318     }
3319 
3320     return offset;
3321 }
3322 
CalculateOffsetRelativeToWindow(uint64_t nanoTimestamp)3323 OffsetF FrameNode::CalculateOffsetRelativeToWindow(uint64_t nanoTimestamp)
3324 {
3325     auto currOffset = geometryNode_->GetFrameOffset();
3326     if (renderContext_ && renderContext_->GetPositionProperty()) {
3327         if (renderContext_->GetPositionProperty()->HasPosition()) {
3328             auto renderPosition =
3329                 ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
3330             currOffset.SetX(static_cast<float>(renderPosition.first));
3331             currOffset.SetY(static_cast<float>(renderPosition.second));
3332         }
3333     }
3334 
3335     auto parent = GetAncestorNodeOfFrame(true);
3336     if (parent) {
3337         auto parentTimestampOffset = parent->GetCachedGlobalOffset();
3338         if (parentTimestampOffset.first == nanoTimestamp) {
3339             auto result = currOffset + parentTimestampOffset.second;
3340             SetCachedGlobalOffset({ nanoTimestamp, result });
3341             return result;
3342         } else {
3343             auto result = currOffset + parent->CalculateOffsetRelativeToWindow(nanoTimestamp);
3344             SetCachedGlobalOffset({ nanoTimestamp, result });
3345             return result;
3346         }
3347     } else {
3348         SetCachedGlobalOffset({ nanoTimestamp, currOffset });
3349         return currOffset;
3350     }
3351 }
3352 
GetNodeContainer()3353 RefPtr<FrameNode> FrameNode::GetNodeContainer()
3354 {
3355     if (GetTag() == "NodeContainer") {
3356         return Claim(this);
3357     }
3358     auto parent = GetParent();
3359     while (parent && parent->GetTag() != "NodeContainer") {
3360         parent = parent->GetParent();
3361     }
3362     return AceType::DynamicCast<FrameNode>(parent);
3363 }
3364 
InitLastArea()3365 void FrameNode::InitLastArea()
3366 {
3367     if (!lastFrameRect_) {
3368         lastFrameRect_ = std::make_unique<RectF>();
3369     }
3370     if (!lastParentOffsetToWindow_) {
3371         lastParentOffsetToWindow_ = std::make_unique<OffsetF>();
3372     }
3373 }
3374 
SetParentLayoutConstraint(const SizeF & size) const3375 bool FrameNode::SetParentLayoutConstraint(const SizeF& size) const
3376 {
3377     LayoutConstraintF layoutConstraint;
3378     layoutConstraint.UpdatePercentReference(size);
3379     layoutConstraint.UpdateMaxSizeWithCheck(size);
3380     layoutConstraint.UpdateIllegalParentIdealSizeWithCheck(OptionalSize(size));
3381     layoutProperty_->UpdateParentLayoutConstraint(layoutConstraint);
3382     return true;
3383 }
3384 
ForceSyncGeometryNode()3385 void FrameNode::ForceSyncGeometryNode()
3386 {
3387     CHECK_NULL_VOID(renderContext_);
3388     oldGeometryNode_.Reset();
3389     renderContext_->SavePaintRect();
3390     renderContext_->SyncGeometryProperties(RawPtr(geometryNode_));
3391 }
3392 
GetCachedGlobalOffset() const3393 const std::pair<uint64_t, OffsetF>& FrameNode::GetCachedGlobalOffset() const
3394 {
3395     return cachedGlobalOffset_;
3396 }
3397 
SetCachedGlobalOffset(const std::pair<uint64_t,OffsetF> & timestampOffset)3398 void FrameNode::SetCachedGlobalOffset(const std::pair<uint64_t, OffsetF>& timestampOffset)
3399 {
3400     cachedGlobalOffset_ = timestampOffset;
3401 }
GetCachedTransformRelativeOffset() const3402 const std::pair<uint64_t, OffsetF>& FrameNode::GetCachedTransformRelativeOffset() const
3403 {
3404     return cachedTransformRelativeOffset_;
3405 }
3406 
SetCachedTransformRelativeOffset(const std::pair<uint64_t,OffsetF> & timestampOffset)3407 void FrameNode::SetCachedTransformRelativeOffset(const std::pair<uint64_t, OffsetF>& timestampOffset)
3408 {
3409     cachedTransformRelativeOffset_ = timestampOffset;
3410 }
3411 } // namespace OHOS::Ace::NG
3412