• 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/memory/ace_type.h"
23 #include "base/memory/referenced.h"
24 #include "base/thread/cancelable_callback.h"
25 #include "base/thread/task_executor.h"
26 #include "base/utils/system_properties.h"
27 #include "base/utils/time_util.h"
28 #include "base/utils/utils.h"
29 #include "core/common/ace_application_info.h"
30 #include "core/components/common/layout/constants.h"
31 #include "core/components_ng/base/inspector.h"
32 #include "core/components_ng/base/ui_node.h"
33 #include "core/components_ng/event/gesture_event_hub.h"
34 #include "core/components_ng/layout/layout_algorithm.h"
35 #include "core/components_ng/layout/layout_wrapper.h"
36 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
37 #include "core/components_ng/pattern/pattern.h"
38 #include "core/components_ng/property/measure_property.h"
39 #include "core/components_ng/property/measure_utils.h"
40 #include "core/components_ng/property/property.h"
41 #include "core/components_ng/render/paint_wrapper.h"
42 #include "core/components_ng/syntax/lazy_for_each_node.h"
43 #include "core/components_v2/inspector/inspector_constants.h"
44 #include "core/event/touch_event.h"
45 #include "core/pipeline_ng/pipeline_context.h"
46 #include "core/pipeline_ng/ui_task_scheduler.h"
47 
48 namespace {
49 constexpr double VISIBLE_RATIO_MIN = 0.0;
50 constexpr double VISIBLE_RATIO_MAX = 1.0;
51 #if defined(PREVIEW)
52 constexpr int32_t SUBSTR_LENGTH = 3;
53 const char DIMENSION_UNIT_VP[] = "vp";
54 #endif
55 } // namespace
56 namespace OHOS::Ace::NG {
57 
58 class FramePorxy {
59 public:
60     struct FrameChildNode {
61         RefPtr<UINode> node;
62         uint32_t startIndex = 0;
63         uint32_t count = 0;
64     };
65 
FramePorxy(FrameNode * frameNode)66     explicit FramePorxy(FrameNode* frameNode) : hostNode_(frameNode) {}
67 
Build()68     void Build()
69     {
70         if (hostNode_ == nullptr || !children_.empty()) {
71             return;
72         }
73         totalCount_ = 0;
74         auto children = hostNode_->GetChildren();
75         int32_t startIndex = 0;
76         int32_t count = 0;
77         for (const auto& child : children) {
78             count = child->FrameCount();
79             children_.push_back({ child, startIndex, count });
80             startIndex += count;
81             totalCount_ += count;
82         }
83         cursor_ = children_.begin();
84     }
85 
AddFrameNode(const RefPtr<UINode> & UiNode,std::list<RefPtr<LayoutWrapper>> & allFrameNodeChildren,std::map<uint32_t,RefPtr<LayoutWrapper>> & partFrameNodeChildren,uint32_t & count)86     static void AddFrameNode(const RefPtr<UINode>& UiNode, std::list<RefPtr<LayoutWrapper>>& allFrameNodeChildren,
87         std::map<uint32_t, RefPtr<LayoutWrapper>>& partFrameNodeChildren, uint32_t& count)
88     {
89         auto frameNode = AceType::DynamicCast<FrameNode>(UiNode);
90         if (frameNode) {
91             allFrameNodeChildren.emplace_back(frameNode);
92             partFrameNodeChildren[count++] = frameNode;
93             return;
94         }
95         auto lazyForEachNode = AceType::DynamicCast<LazyForEachNode>(UiNode);
96         if (lazyForEachNode) {
97             lazyForEachNode->BuildAllChildren();
98         } else {
99             auto customNode = AceType::DynamicCast<CustomNode>(UiNode);
100             if (customNode) {
101                 customNode->Render();
102             }
103         }
104         for (const auto& child : UiNode->GetChildren()) {
105             auto frameNode = AceType::DynamicCast<FrameNode>(child);
106             if (frameNode) {
107                 allFrameNodeChildren.emplace_back(frameNode);
108                 partFrameNodeChildren[count++] = frameNode;
109                 continue;
110             }
111             AddFrameNode(child, allFrameNodeChildren, partFrameNodeChildren, count);
112         }
113     }
114 
GetAllFrameChildren()115     std::list<RefPtr<LayoutWrapper>>& GetAllFrameChildren()
116     {
117         if (!allFrameNodeChildren_.empty()) {
118             return allFrameNodeChildren_;
119         }
120         Build();
121         uint32_t count = 0;
122         for (const auto& child : children_) {
123             AddFrameNode(child.node, allFrameNodeChildren_, partFrameNodeChildren_, count);
124         }
125         return allFrameNodeChildren_;
126     }
127 
FindFrameNodeByIndex(uint32_t index,bool needBuild)128     RefPtr<LayoutWrapper> FindFrameNodeByIndex(uint32_t index, bool needBuild)
129     {
130         while (cursor_ != children_.end()) {
131             if (cursor_->startIndex > index) {
132                 cursor_--;
133                 continue;
134             }
135 
136             if (cursor_->startIndex + cursor_->count > index) {
137                 auto frameNode = AceType::DynamicCast<FrameNode>(
138                     cursor_->node->GetFrameChildByIndex(index - cursor_->startIndex, needBuild));
139                 return frameNode;
140             }
141             cursor_++;
142             if (cursor_ == children_.end()) {
143                 cursor_ = children_.begin();
144                 return nullptr;
145             }
146         }
147         return nullptr;
148     }
149 
GetFrameNodeByIndex(uint32_t index,bool needBuild)150     RefPtr<LayoutWrapper> GetFrameNodeByIndex(uint32_t index, bool needBuild)
151     {
152         auto itor = partFrameNodeChildren_.find(index);
153         if (itor == partFrameNodeChildren_.end()) {
154             Build();
155             auto child = FindFrameNodeByIndex(index, needBuild);
156             if (child) {
157                 partFrameNodeChildren_[index] = child;
158                 return child;
159             }
160             return nullptr;
161         }
162         return itor->second;
163     }
164 
ResetChildren(bool needResetChild=false)165     void ResetChildren(bool needResetChild = false)
166     {
167         allFrameNodeChildren_.clear();
168         partFrameNodeChildren_.clear();
169         totalCount_ = 0;
170         if (needResetChild) {
171             children_.clear();
172             cursor_ = children_.begin();
173         }
174     }
175 
RemoveChildInRenderTree(uint32_t index)176     void RemoveChildInRenderTree(uint32_t index)
177     {
178         auto itor = partFrameNodeChildren_.find(index);
179         if (itor == partFrameNodeChildren_.end()) {
180             return;
181         }
182         itor->second->SetActive(false);
183         partFrameNodeChildren_.erase(itor);
184         while (cursor_ != children_.end()) {
185             if (cursor_->startIndex > index) {
186                 cursor_--;
187                 continue;
188             }
189             if (cursor_->startIndex + cursor_->count > index) {
190                 cursor_->node->DoRemoveChildInRenderTree(index - cursor_->startIndex);
191                 return;
192             }
193             cursor_++;
194             if (cursor_ == children_.end()) {
195                 cursor_ = children_.begin();
196                 return;
197             }
198         }
199     }
200 
RemoveAllChildInRenderTree()201     void RemoveAllChildInRenderTree()
202     {
203         SetAllChildrenInActive();
204         ResetChildren();
205         Build();
206         for (const auto& child : children_) {
207             child.node->DoRemoveChildInRenderTree(0, true);
208         }
209     }
210 
GetTotalCount()211     uint32_t GetTotalCount()
212     {
213         return totalCount_;
214     }
215 
SetAllChildrenInActive()216     void SetAllChildrenInActive()
217     {
218         for (const auto& child : partFrameNodeChildren_) {
219             child.second->SetActive(false);
220         }
221     }
222 
Dump()223     std::string Dump()
224     {
225         std::string info = "FrameChildNode:[";
226         for (const auto& child : children_) {
227             info += std::to_string(child.node->GetId());
228             info += "-";
229             info += std::to_string(child.startIndex);
230             info += "-";
231             info += std::to_string(child.count);
232             info += ",";
233         }
234         info += "] partFrameNodeChildren:[";
235         for (const auto& child : partFrameNodeChildren_) {
236             info += std::to_string(child.second->GetHostNode()->GetId());
237             info += ",";
238         }
239         info += "] TotalCount:";
240         info += std::to_string(totalCount_);
241         return info;
242     }
243 
SetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)244     void SetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
245     {
246         for (const auto& child : children_) {
247             child.node->OnSetCacheCount(cacheCount, itemConstraint);
248         }
249     }
250 
251 private:
252     std::list<FrameChildNode> children_;
253     std::list<FrameChildNode>::iterator cursor_ = children_.begin();
254     std::list<RefPtr<LayoutWrapper>> allFrameNodeChildren_;
255     std::map<uint32_t, RefPtr<LayoutWrapper>> partFrameNodeChildren_;
256     uint32_t totalCount_ = 0;
257     FrameNode* hostNode_ { nullptr };
258 }; // namespace OHOS::Ace::NG
259 
FrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)260 FrameNode::FrameNode(const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
261     : UINode(tag, nodeId, isRoot), LayoutWrapper(WeakClaim(this)), pattern_(pattern),
262       frameProxy_(std::make_unique<FramePorxy>(this))
263 {
264     renderContext_->InitContext(IsRootNode(), pattern_->GetContextParam());
265     paintProperty_ = pattern->CreatePaintProperty();
266     layoutProperty_ = pattern->CreateLayoutProperty();
267     eventHub_ = pattern->CreateEventHub();
268     accessibilityProperty_ = pattern->CreateAccessibilityProperty();
269     // first create make layout property dirty.
270     layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
271     layoutProperty_->SetHost(WeakClaim(this));
272 }
273 
~FrameNode()274 FrameNode::~FrameNode()
275 {
276     for (const auto& destroyCallback : destroyCallbacks_) {
277         destroyCallback();
278     }
279 
280     pattern_->DetachFromFrameNode(this);
281     if (IsOnMainTree()) {
282         OnDetachFromMainTree(false);
283     }
284     TriggerVisibleAreaChangeCallback(true);
285     visibleAreaUserCallbacks_.clear();
286     visibleAreaInnerCallbacks_.clear();
287     auto pipeline = PipelineContext::GetCurrentContext();
288     if (pipeline) {
289         pipeline->RemoveOnAreaChangeNode(GetId());
290         pipeline->RemoveVisibleAreaChangeNode(GetId());
291         pipeline->ChangeMouseStyle(GetId(), MouseFormat::DEFAULT);
292         pipeline->FreeMouseStyleHoldNode(GetId());
293         pipeline->RemoveStoredNode(GetRestoreId());
294         auto dragManager = pipeline->GetDragDropManager();
295         if (dragManager) {
296             dragManager->RemoveDragFrameNode(GetId());
297         }
298     }
299 }
300 
CreateFrameNodeWithTree(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern)301 RefPtr<FrameNode> FrameNode::CreateFrameNodeWithTree(
302     const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern)
303 {
304     auto newChild = CreateFrameNode(tag, nodeId, pattern, true);
305     newChild->SetDepth(1);
306     return newChild;
307 }
308 
GetOrCreateFrameNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)309 RefPtr<FrameNode> FrameNode::GetOrCreateFrameNode(
310     const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
311 {
312     auto frameNode = GetFrameNode(tag, nodeId);
313     if (frameNode) {
314         return frameNode;
315     }
316     auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
317     return CreateFrameNode(tag, nodeId, pattern);
318 }
319 
GetFrameNode(const std::string & tag,int32_t nodeId)320 RefPtr<FrameNode> FrameNode::GetFrameNode(const std::string& tag, int32_t nodeId)
321 {
322     auto frameNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(nodeId);
323     CHECK_NULL_RETURN_NOLOG(frameNode, nullptr);
324     if (frameNode->GetTag() != tag) {
325         LOGE("the tag is changed");
326         ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
327         auto parent = frameNode->GetParent();
328         if (parent) {
329             parent->RemoveChild(frameNode);
330         }
331         return nullptr;
332     }
333     return frameNode;
334 }
335 
CreateFrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)336 RefPtr<FrameNode> FrameNode::CreateFrameNode(
337     const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
338 {
339     auto frameNode = MakeRefPtr<FrameNode>(tag, nodeId, pattern, isRoot);
340     frameNode->InitializePatternAndContext();
341     ElementRegister::GetInstance()->AddUINode(frameNode);
342     return frameNode;
343 }
344 
ProcessOffscreenNode(const RefPtr<FrameNode> & node)345 void FrameNode::ProcessOffscreenNode(const RefPtr<FrameNode>& node)
346 {
347     CHECK_NULL_VOID(node);
348     node->ProcessOffscreenTask();
349     node->MarkModifyDone();
350     node->UpdateLayoutPropertyFlag();
351     node->SetActive();
352     node->isLayoutDirtyMarked_ = true;
353     node->CreateLayoutTask();
354 
355     auto paintProperty = node->GetPaintProperty<PaintProperty>();
356     auto wrapper = node->CreatePaintWrapper();
357     if (wrapper != nullptr) {
358         wrapper->FlushRender();
359     }
360     paintProperty->CleanDirty();
361     auto pipeline = PipelineContext::GetCurrentContext();
362     CHECK_NULL_VOID(pipeline);
363     pipeline->FlushMessages();
364     node->SetActive(false);
365 }
366 
InitializePatternAndContext()367 void FrameNode::InitializePatternAndContext()
368 {
369     eventHub_->AttachHost(WeakClaim(this));
370     pattern_->AttachToFrameNode(WeakClaim(this));
371     accessibilityProperty_->SetHost(WeakClaim(this));
372     renderContext_->SetRequestFrame([weak = WeakClaim(this)] {
373         auto frameNode = weak.Upgrade();
374         CHECK_NULL_VOID(frameNode);
375         if (frameNode->IsOnMainTree()) {
376             auto context = frameNode->GetContext();
377             CHECK_NULL_VOID(context);
378             context->RequestFrame();
379             return;
380         }
381         frameNode->hasPendingRequest_ = true;
382     });
383     renderContext_->SetHostNode(WeakClaim(this));
384     // Initialize FocusHub
385     if (pattern_->GetFocusPattern().GetFocusType() != FocusType::DISABLE) {
386         GetOrCreateFocusHub();
387     }
388 }
389 
DumpOverlayInfo()390 void FrameNode::DumpOverlayInfo()
391 {
392     if (!layoutProperty_->IsOverlayNode()) {
393         return;
394     }
395     DumpLog::GetInstance().AddDesc(std::string("IsOverlayNode: ").append(std::string("true")));
396     Dimension offsetX, offsetY;
397     layoutProperty_->GetOverlayOffset(offsetX, offsetY);
398     DumpLog::GetInstance().AddDesc(
399         std::string("OverlayOffset: ").append(offsetX.ToString()).append(std::string(", ")).append(offsetY.ToString()));
400 }
401 
DumpInfo()402 void FrameNode::DumpInfo()
403 {
404     DumpLog::GetInstance().AddDesc(std::string("FrameRect: ").append(geometryNode_->GetFrameRect().ToString()));
405     DumpLog::GetInstance().AddDesc(
406         std::string("BackgroundColor: ").append(renderContext_->GetBackgroundColor()->ColorToString()));
407     DumpLog::GetInstance().AddDesc(std::string("ParentLayoutConstraint: ")
408                                        .append(geometryNode_->GetParentLayoutConstraint().has_value()
409                                                    ? geometryNode_->GetParentLayoutConstraint().value().ToString()
410                                                    : "NA"));
411     DumpLog::GetInstance().AddDesc(std::string("top: ")
412                                        .append(std::to_string(GetOffsetRelativeToWindow().GetY()))
413                                        .append(" left: ")
414                                        .append(std::to_string(GetOffsetRelativeToWindow().GetX())));
415     DumpLog::GetInstance().AddDesc(std::string("Active: ").append(std::to_string(static_cast<int32_t>(IsActive()))));
416     DumpLog::GetInstance().AddDesc(std::string("Visible: ")
417                                        .append(std::to_string(static_cast<int32_t>(
418                                            layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)))));
419     if (layoutProperty_->GetPaddingProperty()) {
420         DumpLog::GetInstance().AddDesc(
421             std::string("Padding: ").append(layoutProperty_->GetPaddingProperty()->ToString().c_str()));
422     }
423     if (layoutProperty_->GetBorderWidthProperty()) {
424         DumpLog::GetInstance().AddDesc(
425             std::string("Border: ").append(layoutProperty_->GetBorderWidthProperty()->ToString().c_str()));
426     }
427     if (layoutProperty_->GetMarginProperty()) {
428         DumpLog::GetInstance().AddDesc(
429             std::string("Margin: ").append(layoutProperty_->GetMarginProperty()->ToString().c_str()));
430     }
431     if (layoutProperty_->GetCalcLayoutConstraint()) {
432         DumpLog::GetInstance().AddDesc(std::string("User defined constraint: ")
433                                            .append(layoutProperty_->GetCalcLayoutConstraint()->ToString().c_str()));
434     }
435     DumpLog::GetInstance().AddDesc(std::string("compid: ").append(propInspectorId_.value_or("")));
436     DumpLog::GetInstance().AddDesc(std::string("ContentConstraint: ")
437                                        .append(layoutProperty_->GetContentLayoutConstraint().has_value()
438                                                    ? layoutProperty_->GetContentLayoutConstraint().value().ToString()
439                                                    : "NA"));
440     DumpOverlayInfo();
441     DumpLog::GetInstance().AddDesc(
442         std::string("PaintRect: ").append(renderContext_->GetPaintRectWithTransform().ToString()));
443     DumpLog::GetInstance().AddDesc(std::string("FrameProxy: ").append(frameProxy_->Dump().c_str()));
444     if (pattern_) {
445         pattern_->DumpInfo();
446     }
447     if (renderContext_) {
448         renderContext_->DumpInfo();
449     }
450 }
451 
FocusToJsonValue(std::unique_ptr<JsonValue> & json) const452 void FrameNode::FocusToJsonValue(std::unique_ptr<JsonValue>& json) const
453 {
454     bool enabled = true;
455     bool focusable = false;
456     bool focused = false;
457     bool defaultFocus = false;
458     bool groupDefaultFocus = false;
459     bool focusOnTouch = false;
460     int32_t tabIndex = 0;
461     auto focusHub = GetFocusHub();
462     if (focusHub) {
463         enabled = focusHub->IsEnabled();
464         focusable = focusHub->IsFocusable();
465         focused = focusHub->IsCurrentFocus();
466         defaultFocus = focusHub->IsDefaultFocus();
467         groupDefaultFocus = focusHub->IsDefaultGroupFocus();
468         focusOnTouch = focusHub->IsFocusOnTouch().value_or(false);
469         tabIndex = focusHub->GetTabIndex();
470     }
471     json->Put("enabled", enabled);
472     json->Put("focusable", focusable);
473     json->Put("focused", focused);
474     json->Put("defaultFocus", defaultFocus);
475     json->Put("groupDefaultFocus", groupDefaultFocus);
476     json->Put("focusOnTouch", focusOnTouch);
477     json->Put("tabIndex", tabIndex);
478 }
479 
MouseToJsonValue(std::unique_ptr<JsonValue> & json) const480 void FrameNode::MouseToJsonValue(std::unique_ptr<JsonValue>& json) const
481 {
482     std::string hoverEffect = "HoverEffect.Auto";
483     auto inputEventHub = GetOrCreateInputEventHub();
484     if (inputEventHub) {
485         hoverEffect = inputEventHub->GetHoverEffectStr();
486     }
487     json->Put("hoverEffect", hoverEffect.c_str());
488 }
489 
TouchToJsonValue(std::unique_ptr<JsonValue> & json) const490 void FrameNode::TouchToJsonValue(std::unique_ptr<JsonValue>& json) const
491 {
492     bool touchable = true;
493     std::string hitTestMode = "HitTestMode.Default";
494     auto gestureEventHub = GetOrCreateGestureEventHub();
495     std::vector<DimensionRect> responseRegion;
496     std::vector<DimensionRect> mouseResponseRegion;
497     if (gestureEventHub) {
498         touchable = gestureEventHub->GetTouchable();
499         hitTestMode = gestureEventHub->GetHitTestModeStr();
500         responseRegion = gestureEventHub->GetResponseRegion();
501         mouseResponseRegion = gestureEventHub->GetMouseResponseRegion();
502     }
503     json->Put("touchable", touchable);
504     json->Put("hitTestBehavior", hitTestMode.c_str());
505     auto jsArr = JsonUtil::CreateArray(true);
506     for (int32_t i = 0; i < static_cast<int32_t>(responseRegion.size()); ++i) {
507         auto iStr = std::to_string(i);
508         jsArr->Put(iStr.c_str(), responseRegion[i].ToJsonString().c_str());
509     }
510     json->Put("responseRegion", jsArr);
511     for (int32_t i = 0; i < static_cast<int32_t>(mouseResponseRegion.size()); ++i) {
512         auto iStr = std::to_string(i);
513         jsArr->Put(iStr.c_str(), mouseResponseRegion[i].ToJsonString().c_str());
514     }
515     json->Put("mouseResponseRegion", jsArr);
516 }
517 
GeometryNodeToJsonValue(std::unique_ptr<JsonValue> & json) const518 void FrameNode::GeometryNodeToJsonValue(std::unique_ptr<JsonValue>& json) const
519 {
520 #if defined(PREVIEW)
521     bool hasIdealWidth = false;
522     bool hasIdealHeight = false;
523     if (layoutProperty_ && layoutProperty_->GetCalcLayoutConstraint()) {
524         auto selfIdealSize = layoutProperty_->GetCalcLayoutConstraint()->selfIdealSize;
525         hasIdealWidth = selfIdealSize.has_value() && selfIdealSize.value().Width().has_value();
526         hasIdealHeight = selfIdealSize.has_value() && selfIdealSize.value().Height().has_value();
527     }
528 
529     auto jsonSize = json->GetValue("size");
530     if (!hasIdealWidth) {
531         auto idealWidthVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Width()).ConvertToVp());
532         auto widthStr =
533             (idealWidthVpStr.substr(0, idealWidthVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP).c_str();
534         json->Put("width", widthStr);
535         if (jsonSize) {
536             jsonSize->Put("width", widthStr);
537         }
538     }
539 
540     if (!hasIdealHeight) {
541         auto idealHeightVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Height()).ConvertToVp());
542         auto heightStr =
543             (idealHeightVpStr.substr(0, idealHeightVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP).c_str();
544         json->Put("height", heightStr);
545         if (jsonSize) {
546             jsonSize->Put("height", heightStr);
547         }
548     }
549 #endif
550 }
551 
ToJsonValue(std::unique_ptr<JsonValue> & json) const552 void FrameNode::ToJsonValue(std::unique_ptr<JsonValue>& json) const
553 {
554     if (renderContext_) {
555         renderContext_->ToJsonValue(json);
556     }
557     // scrollable in AccessibilityProperty
558     ACE_PROPERTY_TO_JSON_VALUE(accessibilityProperty_, AccessibilityProperty);
559     ACE_PROPERTY_TO_JSON_VALUE(layoutProperty_, LayoutProperty);
560     ACE_PROPERTY_TO_JSON_VALUE(paintProperty_, PaintProperty);
561     ACE_PROPERTY_TO_JSON_VALUE(pattern_, Pattern);
562     if (eventHub_) {
563         eventHub_->ToJsonValue(json);
564     }
565     FocusToJsonValue(json);
566     MouseToJsonValue(json);
567     TouchToJsonValue(json);
568     GeometryNodeToJsonValue(json);
569     json->Put("id", propInspectorId_.value_or("").c_str());
570 }
571 
FromJson(const std::unique_ptr<JsonValue> & json)572 void FrameNode::FromJson(const std::unique_ptr<JsonValue>& json)
573 {
574     if (renderContext_) {
575         LOGD("UITree start decode renderContext");
576         renderContext_->FromJson(json);
577     }
578     LOGD("UITree start decode accessibilityProperty");
579     accessibilityProperty_->FromJson(json);
580     LOGD("UITree start decode layoutProperty");
581     layoutProperty_->FromJson(json);
582     LOGD("UITree start decode paintProperty");
583     paintProperty_->FromJson(json);
584     LOGD("UITree start decode pattern");
585     pattern_->FromJson(json);
586     if (eventHub_) {
587         LOGD("UITree start decode eventHub");
588         eventHub_->FromJson(json);
589     }
590 }
591 
OnAttachToMainTree(bool recursive)592 void FrameNode::OnAttachToMainTree(bool recursive)
593 {
594     eventHub_->FireOnAppear();
595     renderContext_->OnNodeAppear(recursive);
596     if (IsResponseRegion() || HasPositionProp()) {
597         auto parent = GetParent();
598         while (parent) {
599             auto frameNode = AceType::DynamicCast<FrameNode>(parent);
600             if (frameNode) {
601                 frameNode->MarkResponseRegion(true);
602             }
603             parent = parent->GetParent();
604         }
605     }
606     // node may have been measured before AttachToMainTree
607     if (geometryNode_->GetParentLayoutConstraint().has_value() && !UseOffscreenProcess()) {
608         layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE_SELF);
609     }
610 
611     UINode::OnAttachToMainTree(recursive);
612 
613     if (!hasPendingRequest_) {
614         return;
615     }
616     auto context = GetContext();
617     CHECK_NULL_VOID(context);
618     context->RequestFrame();
619     hasPendingRequest_ = false;
620 }
621 
OnConfigurationUpdate(const OnConfigurationChange & configurationChange)622 void FrameNode::OnConfigurationUpdate(const OnConfigurationChange& configurationChange)
623 {
624     if (configurationChange.languageUpdate) {
625         pattern_->OnLanguageConfigurationUpdate();
626         MarkModifyDone();
627         MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
628     }
629     if (configurationChange.colorModeUpdate) {
630         pattern_->OnColorConfigurationUpdate();
631         MarkModifyDone();
632         MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
633     }
634 }
635 
OnVisibleChange(bool isVisible)636 void FrameNode::OnVisibleChange(bool isVisible)
637 {
638     pattern_->OnVisibleChange(isVisible);
639     UpdateChildrenVisible(isVisible);
640     TriggerVisibleAreaChangeCallback(true);
641 }
642 
OnDetachFromMainTree(bool recursive)643 void FrameNode::OnDetachFromMainTree(bool recursive)
644 {
645     eventHub_->FireOnDisappear();
646     renderContext_->OnNodeDisappear(recursive);
647 }
648 
SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper> & dirty)649 void FrameNode::SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper>& dirty)
650 {
651     LOGD("SwapDirtyLayoutWrapperOnMainThread, %{public}s", GetTag().c_str());
652     CHECK_NULL_VOID(dirty);
653 
654     // update new layout constrain.
655     layoutProperty_->UpdateLayoutConstraint(dirty->GetLayoutProperty());
656 
657     // active change flag judge.
658     SetActive(dirty->IsActive());
659     if (!isActive_) {
660         LOGD("current node is inactive, don't need to render");
661         return;
662     }
663 
664     // update layout size.
665     bool frameSizeChange = geometryNode_->GetFrameSize() != dirty->GetGeometryNode()->GetFrameSize();
666     bool frameOffsetChange = geometryNode_->GetFrameOffset() != dirty->GetGeometryNode()->GetFrameOffset();
667     bool contentSizeChange = geometryNode_->GetContentSize() != dirty->GetGeometryNode()->GetContentSize();
668     bool contentOffsetChange = geometryNode_->GetContentOffset() != dirty->GetGeometryNode()->GetContentOffset();
669 
670     SetGeometryNode(dirty->GetGeometryNode());
671 
672     const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
673     if (geometryTransition != nullptr && geometryTransition->IsRunning()) {
674         geometryTransition->DidLayout(dirty);
675     } else if (frameSizeChange || frameOffsetChange || HasPositionProp() ||
676                (pattern_->GetContextParam().has_value() && contentSizeChange)) {
677         renderContext_->SyncGeometryProperties(RawPtr(dirty->GetGeometryNode()));
678     }
679 
680     // clean layout flag.
681     layoutProperty_->CleanDirty();
682     DirtySwapConfig config { frameSizeChange, frameOffsetChange, contentSizeChange, contentOffsetChange };
683     // check if need to paint content.
684     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
685     CHECK_NULL_VOID(layoutAlgorithmWrapper);
686     config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure() || dirty->SkipMeasureContent();
687     config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
688     if ((config.skipMeasure == false) && (config.skipLayout == false) && GetInspectorId().has_value()) {
689         auto pipeline = PipelineContext::GetCurrentContext();
690         CHECK_NULL_VOID(pipeline);
691         pipeline->OnLayoutCompleted(GetInspectorId()->c_str());
692     }
693     auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(dirty, config);
694     // TODO: temp use and need to delete.
695     needRerender = needRerender || pattern_->OnDirtyLayoutWrapperSwap(dirty, config.skipMeasure, config.skipLayout);
696     if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
697         MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
698     }
699 
700     // update border.
701     if (layoutProperty_->GetBorderWidthProperty()) {
702         if (!renderContext_->HasBorderColor()) {
703             BorderColorProperty borderColorProperty;
704             borderColorProperty.SetColor(Color::BLACK);
705             renderContext_->UpdateBorderColor(borderColorProperty);
706         }
707         if (!renderContext_->HasBorderStyle()) {
708             BorderStyleProperty borderStyleProperty;
709             borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
710             renderContext_->UpdateBorderStyle(borderStyleProperty);
711         }
712         if (layoutProperty_->GetLayoutConstraint().has_value()) {
713             renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
714                 ScaleProperty::CreateScaleProperty(),
715                 layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
716         } else {
717             renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
718                 ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
719         }
720     }
721 
722     // update background
723     if (builderFunc_) {
724         auto builderNode = builderFunc_();
725         auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
726             AceType::MakeRefPtr<LinearLayoutPattern>(true));
727         builderNode->MountToParent(columnNode);
728         SetBackgroundLayoutConstraint(columnNode);
729         renderContext_->CreateBackgroundPixelMap(columnNode);
730         builderFunc_ = nullptr;
731         backgroundNode_ = columnNode;
732     }
733 
734     // update focus state
735     auto focusHub = GetFocusHub();
736     if (focusHub && focusHub->IsCurrentFocus()) {
737         focusHub->ClearFocusState(false);
738         focusHub->PaintFocusState(false);
739     }
740 
741     // rebuild child render node.
742     RebuildRenderContextTree();
743 }
744 
SetBackgroundLayoutConstraint(const RefPtr<FrameNode> & customNode)745 void FrameNode::SetBackgroundLayoutConstraint(const RefPtr<FrameNode>& customNode)
746 {
747     CHECK_NULL_VOID(customNode);
748     LayoutConstraintF layoutConstraint;
749     layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
750     layoutConstraint.percentReference.SetWidth(geometryNode_->GetFrameSize().Width());
751     layoutConstraint.percentReference.SetHeight(geometryNode_->GetFrameSize().Height());
752     layoutConstraint.maxSize.SetWidth(geometryNode_->GetFrameSize().Width());
753     layoutConstraint.maxSize.SetHeight(geometryNode_->GetFrameSize().Height());
754     customNode->GetGeometryNode()->SetParentLayoutConstraint(layoutConstraint);
755 }
756 
AdjustGridOffset()757 void FrameNode::AdjustGridOffset()
758 {
759     if (!isActive_) {
760         return;
761     }
762     if (layoutProperty_->UpdateGridOffset(Claim(this))) {
763         renderContext_->UpdateOffset(OffsetT<Dimension>());
764         renderContext_->UpdateAnchor(OffsetT<Dimension>());
765         renderContext_->SyncGeometryProperties(RawPtr(GetGeometryNode()));
766     }
767 }
768 
ClearUserOnAreaChange()769 void FrameNode::ClearUserOnAreaChange()
770 {
771     if (eventHub_) {
772         eventHub_->ClearUserOnAreaChanged();
773     }
774 }
775 
SetOnAreaChangeCallback(OnAreaChangedFunc && callback)776 void FrameNode::SetOnAreaChangeCallback(OnAreaChangedFunc&& callback)
777 {
778     if (!lastFrameRect_) {
779         lastFrameRect_ = std::make_unique<RectF>();
780     }
781     if (!lastParentOffsetToWindow_) {
782         lastParentOffsetToWindow_ = std::make_unique<OffsetF>();
783     }
784     eventHub_->SetOnAreaChanged(std::move(callback));
785 }
786 
TriggerOnAreaChangeCallback()787 void FrameNode::TriggerOnAreaChangeCallback()
788 {
789     if (eventHub_->HasOnAreaChanged() && lastFrameRect_ && lastParentOffsetToWindow_) {
790         auto currFrameRect = geometryNode_->GetFrameRect();
791         auto currParentOffsetToWindow = GetOffsetRelativeToWindow() - currFrameRect.GetOffset();
792         if (currFrameRect != *lastFrameRect_ || currParentOffsetToWindow != *lastParentOffsetToWindow_) {
793             eventHub_->FireOnAreaChanged(
794                 *lastFrameRect_, *lastParentOffsetToWindow_, currFrameRect, currParentOffsetToWindow);
795             *lastFrameRect_ = currFrameRect;
796             *lastParentOffsetToWindow_ = currParentOffsetToWindow;
797         }
798     }
799     pattern_->OnAreaChangedInner();
800 }
801 
TriggerVisibleAreaChangeCallback(bool forceDisappear)802 void FrameNode::TriggerVisibleAreaChangeCallback(bool forceDisappear)
803 {
804     auto context = PipelineContext::GetCurrentContext();
805     CHECK_NULL_VOID(context);
806 
807     bool isFrameDisappear = forceDisappear || !context->GetOnShow() || !IsOnMainTree();
808     if (!isFrameDisappear) {
809         bool curFrameIsActive = isActive_;
810         bool curIsVisible = IsVisible();
811         auto parent = GetParent();
812         while (parent) {
813             auto parentFrame = AceType::DynamicCast<FrameNode>(parent);
814             if (!parentFrame) {
815                 parent = parent->GetParent();
816                 continue;
817             }
818             if (!parentFrame->isActive_) {
819                 curFrameIsActive = false;
820                 break;
821             }
822             if (!parentFrame->IsVisible()) {
823                 curIsVisible = false;
824                 break;
825             }
826             parent = parent->GetParent();
827         }
828         isFrameDisappear = !curIsVisible || !curFrameIsActive;
829     }
830 
831     if (isFrameDisappear) {
832         if (!NearEqual(lastVisibleRatio_, VISIBLE_RATIO_MIN)) {
833             ProcessAllVisibleCallback(visibleAreaUserCallbacks_, VISIBLE_RATIO_MIN);
834             ProcessAllVisibleCallback(visibleAreaInnerCallbacks_, VISIBLE_RATIO_MIN);
835             lastVisibleRatio_ = VISIBLE_RATIO_MIN;
836         }
837         return;
838     }
839 
840     auto frameRect = renderContext_->GetPaintRectWithTransform();
841     frameRect.SetOffset(GetOffsetRelativeToWindow());
842     auto visibleRect = frameRect;
843     RectF parentRect;
844     auto parentUi = GetParent();
845     if (!parentUi) {
846         visibleRect.SetWidth(0.0f);
847         visibleRect.SetHeight(0.0f);
848     }
849     while (parentUi) {
850         auto parentFrame = AceType::DynamicCast<FrameNode>(parentUi);
851         if (!parentFrame) {
852             parentUi = parentUi->GetParent();
853             continue;
854         }
855         parentRect = parentFrame->GetRenderContext()->GetPaintRectWithTransform();
856         parentRect.SetOffset(parentFrame->GetOffsetRelativeToWindow());
857         visibleRect = visibleRect.Constrain(parentRect);
858         parentUi = parentUi->GetParent();
859     }
860 
861     double currentVisibleRatio =
862         std::clamp(CalculateCurrentVisibleRatio(visibleRect, frameRect), VISIBLE_RATIO_MIN, VISIBLE_RATIO_MAX);
863     if (!NearEqual(currentVisibleRatio, lastVisibleRatio_)) {
864         ProcessAllVisibleCallback(visibleAreaUserCallbacks_, currentVisibleRatio);
865         ProcessAllVisibleCallback(visibleAreaInnerCallbacks_, currentVisibleRatio);
866         lastVisibleRatio_ = currentVisibleRatio;
867     }
868 }
869 
CalculateCurrentVisibleRatio(const RectF & visibleRect,const RectF & renderRect)870 double FrameNode::CalculateCurrentVisibleRatio(const RectF& visibleRect, const RectF& renderRect)
871 {
872     if (!visibleRect.IsValid() || !renderRect.IsValid()) {
873         return 0.0;
874     }
875     return visibleRect.Width() * visibleRect.Height() / (renderRect.Width() * renderRect.Height());
876 }
877 
ProcessAllVisibleCallback(std::unordered_map<double,VisibleCallbackInfo> & visibleAreaCallbacks,double currentVisibleRatio)878 void FrameNode::ProcessAllVisibleCallback(
879     std::unordered_map<double, VisibleCallbackInfo>& visibleAreaCallbacks, double currentVisibleRatio)
880 {
881     bool isHandled = false;
882     for (auto& nodeCallbackInfo : visibleAreaCallbacks) {
883         auto callbackRatio = nodeCallbackInfo.first;
884         auto callbackIsVisible = nodeCallbackInfo.second.isCurrentVisible;
885         if (GreatNotEqual(currentVisibleRatio, callbackRatio) && !callbackIsVisible) {
886             OnVisibleAreaChangeCallback(nodeCallbackInfo.second, true, currentVisibleRatio, isHandled);
887             isHandled = true;
888             continue;
889         }
890 
891         if (LessNotEqual(currentVisibleRatio, callbackRatio) && callbackIsVisible) {
892             OnVisibleAreaChangeCallback(nodeCallbackInfo.second, false, currentVisibleRatio, isHandled);
893             isHandled = true;
894             continue;
895         }
896 
897         if (NearEqual(currentVisibleRatio, callbackRatio) && NearEqual(callbackRatio, VISIBLE_RATIO_MIN)) {
898             if (callbackIsVisible) {
899                 OnVisibleAreaChangeCallback(nodeCallbackInfo.second, false, VISIBLE_RATIO_MIN, isHandled);
900             } else {
901                 OnVisibleAreaChangeCallback(nodeCallbackInfo.second, true, VISIBLE_RATIO_MIN, isHandled);
902             }
903             isHandled = true;
904         } else if (NearEqual(currentVisibleRatio, callbackRatio) && NearEqual(callbackRatio, VISIBLE_RATIO_MAX)) {
905             if (!callbackIsVisible) {
906                 OnVisibleAreaChangeCallback(nodeCallbackInfo.second, true, VISIBLE_RATIO_MAX, isHandled);
907             } else {
908                 OnVisibleAreaChangeCallback(nodeCallbackInfo.second, false, VISIBLE_RATIO_MAX, isHandled);
909             }
910             isHandled = true;
911         }
912     }
913 }
914 
OnVisibleAreaChangeCallback(VisibleCallbackInfo & callbackInfo,bool visibleType,double currentVisibleRatio,bool isHandled)915 void FrameNode::OnVisibleAreaChangeCallback(
916     VisibleCallbackInfo& callbackInfo, bool visibleType, double currentVisibleRatio, bool isHandled)
917 {
918     callbackInfo.isCurrentVisible = visibleType;
919     if (callbackInfo.callback && !isHandled) {
920         callbackInfo.callback(visibleType, currentVisibleRatio);
921     }
922 }
923 
SetActive(bool active)924 void FrameNode::SetActive(bool active)
925 {
926     bool activeChanged = false;
927     if (active && !isActive_) {
928         pattern_->OnActive();
929         isActive_ = true;
930         activeChanged = true;
931     }
932     if (!active && isActive_) {
933         pattern_->OnInActive();
934         isActive_ = false;
935         activeChanged = true;
936     }
937     if (activeChanged) {
938         auto parent = GetAncestorNodeOfFrame();
939         if (parent) {
940             parent->MarkNeedSyncRenderTree();
941         }
942     }
943     if (GetTag() == V2::TAB_CONTENT_ITEM_ETS_TAG) {
944         SetJSViewActive(active);
945     }
946 }
947 
SetGeometryNode(const RefPtr<GeometryNode> & node)948 void FrameNode::SetGeometryNode(const RefPtr<GeometryNode>& node)
949 {
950     geometryNode_ = node;
951 }
952 
CreateLayoutTask(bool forceUseMainThread)953 std::optional<UITask> FrameNode::CreateLayoutTask(bool forceUseMainThread)
954 {
955     if (!isLayoutDirtyMarked_) {
956         return std::nullopt;
957     }
958     SetRootMeasureNode(true);
959     UpdateLayoutPropertyFlag();
960     {
961         ACE_SCOPED_TRACE("Measure");
962         Measure(GetLayoutConstraint());
963     }
964     {
965         ACE_SCOPED_TRACE("Layout");
966         Layout();
967     }
968     SetRootMeasureNode(false);
969     return std::nullopt;
970 }
971 
CreateRenderTask(bool forceUseMainThread)972 std::optional<UITask> FrameNode::CreateRenderTask(bool forceUseMainThread)
973 {
974     if (!isRenderDirtyMarked_) {
975         return std::nullopt;
976     }
977     auto wrapper = CreatePaintWrapper();
978     CHECK_NULL_RETURN_NOLOG(wrapper, std::nullopt);
979     auto task = [weak = WeakClaim(this), wrapper, paintProperty = paintProperty_]() {
980         ACE_SCOPED_TRACE("FrameNode::RenderTask");
981         auto self = weak.Upgrade();
982         wrapper->FlushRender();
983         paintProperty->CleanDirty();
984 
985         if (self->GetInspectorId()) {
986             auto pipeline = PipelineContext::GetCurrentContext();
987             CHECK_NULL_VOID(pipeline);
988             pipeline->SetNeedRenderNode(self);
989         }
990     };
991     if (forceUseMainThread || wrapper->CheckShouldRunOnMain()) {
992         return UITask(std::move(task), MAIN_TASK);
993     }
994     return UITask(std::move(task), wrapper->CanRunOnWhichThread());
995 }
996 
GetLayoutConstraint() const997 LayoutConstraintF FrameNode::GetLayoutConstraint() const
998 {
999     if (geometryNode_->GetParentLayoutConstraint().has_value()) {
1000         return geometryNode_->GetParentLayoutConstraint().value();
1001     }
1002     LayoutConstraintF layoutConstraint;
1003     layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
1004     auto rootWidth = PipelineContext::GetCurrentRootWidth();
1005     auto rootHeight = PipelineContext::GetCurrentRootHeight();
1006     layoutConstraint.percentReference.SetWidth(rootWidth);
1007     layoutConstraint.percentReference.SetHeight(rootHeight);
1008     layoutConstraint.maxSize.SetWidth(rootWidth);
1009     layoutConstraint.maxSize.SetHeight(rootHeight);
1010     return layoutConstraint;
1011 }
1012 
GetParentGlobalOffset() const1013 OffsetF FrameNode::GetParentGlobalOffset() const
1014 {
1015     auto parent = GetAncestorNodeOfFrame();
1016     if (!parent) {
1017         return { 0.0f, 0.0f };
1018     }
1019     return parent->geometryNode_->GetParentGlobalOffset();
1020 }
1021 
UpdateLayoutPropertyFlag()1022 void FrameNode::UpdateLayoutPropertyFlag()
1023 {
1024     auto selfFlag = layoutProperty_->GetPropertyChangeFlag();
1025     if (!CheckUpdateByChildRequest(selfFlag)) {
1026         return;
1027     }
1028     if (CheckForceParentMeasureFlag(selfFlag)) {
1029         return;
1030     }
1031     auto flag = PROPERTY_UPDATE_NORMAL;
1032     const auto& children = GetChildren();
1033     for (const auto& child : children) {
1034         child->UpdateLayoutPropertyFlag();
1035         child->AdjustParentLayoutFlag(flag);
1036         if (CheckForceParentMeasureFlag(selfFlag)) {
1037             break;
1038         }
1039     }
1040     if (CheckForceParentMeasureFlag(flag)) {
1041         layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
1042     }
1043 }
1044 
ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeFlag)1045 void FrameNode::ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeFlag)
1046 {
1047     layoutProperty_->UpdatePropertyChangeFlag(propertyChangeFlag);
1048 }
1049 
AdjustParentLayoutFlag(PropertyChangeFlag & flag)1050 void FrameNode::AdjustParentLayoutFlag(PropertyChangeFlag& flag)
1051 {
1052     flag = flag | layoutProperty_->GetPropertyChangeFlag();
1053 }
1054 
CreateLayoutWrapper(bool forceMeasure,bool forceLayout)1055 RefPtr<LayoutWrapperNode> FrameNode::CreateLayoutWrapper(bool forceMeasure, bool forceLayout)
1056 {
1057     return UpdateLayoutWrapper(nullptr, forceMeasure, forceLayout);
1058 }
1059 
UpdateLayoutWrapper(RefPtr<LayoutWrapperNode> layoutWrapper,bool forceMeasure,bool forceLayout)1060 RefPtr<LayoutWrapperNode> FrameNode::UpdateLayoutWrapper(
1061     RefPtr<LayoutWrapperNode> layoutWrapper, bool forceMeasure, bool forceLayout)
1062 {
1063     CHECK_NULL_RETURN_NOLOG(layoutProperty_, nullptr);
1064     CHECK_NULL_RETURN_NOLOG(pattern_, nullptr);
1065     if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
1066         if (!layoutWrapper) {
1067             layoutWrapper =
1068                 MakeRefPtr<LayoutWrapperNode>(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
1069         } else {
1070             layoutWrapper->Update(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
1071         }
1072         layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
1073         isLayoutDirtyMarked_ = false;
1074         return layoutWrapper;
1075     }
1076 
1077     pattern_->BeforeCreateLayoutWrapper();
1078     if (forceMeasure) {
1079         layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
1080     }
1081     if (forceLayout) {
1082         layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
1083     }
1084     auto flag = layoutProperty_->GetPropertyChangeFlag();
1085     // It is necessary to copy the layoutProperty property to prevent the layoutProperty property from being
1086     // modified during the layout process, resulting in the problem of judging whether the front-end setting value
1087     // changes the next time js is executed.
1088     if (!layoutWrapper) {
1089         layoutWrapper =
1090             MakeRefPtr<LayoutWrapperNode>(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
1091     } else {
1092         layoutWrapper->Update(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
1093     }
1094     LOGD("%{public}s create layout wrapper: %{public}x, %{public}d, %{public}d", GetTag().c_str(), flag, forceMeasure,
1095         forceLayout);
1096     do {
1097         if (CheckNeedMeasure(flag) || forceMeasure) {
1098             layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm()));
1099             bool forceChildMeasure = CheckMeasureFlag(flag) || CheckMeasureSelfAndChildFlag(flag) || forceMeasure;
1100             UpdateChildrenLayoutWrapper(layoutWrapper, forceChildMeasure, false);
1101             break;
1102         }
1103         if (CheckNeedLayout(flag) || forceLayout) {
1104             layoutWrapper->SetLayoutAlgorithm(
1105                 MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm(), true, false));
1106             UpdateChildrenLayoutWrapper(layoutWrapper, false, false);
1107             break;
1108         }
1109         layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
1110     } while (false);
1111     // check position flag.
1112     layoutWrapper->SetOutOfLayout(renderContext_->HasPosition());
1113     layoutWrapper->SetActive(isActive_);
1114     layoutWrapper->SetIsOverlayNode(layoutProperty_->IsOverlayNode());
1115     isLayoutDirtyMarked_ = false;
1116     return layoutWrapper;
1117 }
1118 
UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapperNode> & self,bool forceMeasure,bool forceLayout)1119 void FrameNode::UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapperNode>& self, bool forceMeasure, bool forceLayout)
1120 {
1121     const auto& children = GetChildren();
1122     for (const auto& child : children) {
1123         child->AdjustLayoutWrapperTree(self, forceMeasure, forceLayout);
1124     }
1125 }
1126 
AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode> & parent,bool forceMeasure,bool forceLayout)1127 void FrameNode::AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode>& parent, bool forceMeasure, bool forceLayout)
1128 {
1129     ACE_DCHECK(parent);
1130     CHECK_NULL_VOID(layoutProperty_);
1131     const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
1132     if (geometryTransition != nullptr && geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
1133         return;
1134     }
1135     auto layoutWrapper = CreateLayoutWrapper(forceMeasure, forceLayout);
1136     parent->AppendChild(layoutWrapper, layoutProperty_->IsOverlayNode());
1137 }
1138 
CreatePaintWrapper()1139 RefPtr<PaintWrapper> FrameNode::CreatePaintWrapper()
1140 {
1141     pattern_->BeforeCreatePaintWrapper();
1142     isRenderDirtyMarked_ = false;
1143     auto paintMethod = pattern_->CreateNodePaintMethod();
1144     // It is necessary to copy the layoutProperty property to prevent the paintProperty_ property from being
1145     // modified during the paint process, resulting in the problem of judging whether the front-end setting value
1146     // changes the next time js is executed.
1147     if (paintMethod) {
1148         auto paintWrapper = MakeRefPtr<PaintWrapper>(renderContext_, geometryNode_->Clone(), paintProperty_->Clone());
1149         paintWrapper->SetNodePaintMethod(paintMethod);
1150         return paintWrapper;
1151     }
1152     if (renderContext_->GetAccessibilityFocus().value_or(false)) {
1153         auto paintWrapper = MakeRefPtr<PaintWrapper>(renderContext_, geometryNode_->Clone(), paintProperty_->Clone());
1154         paintWrapper->SetNodePaintMethod(MakeRefPtr<NodePaintMethod>());
1155         return paintWrapper;
1156     }
1157     return nullptr;
1158 }
1159 
PostTask(std::function<void ()> && task,TaskExecutor::TaskType taskType)1160 void FrameNode::PostTask(std::function<void()>&& task, TaskExecutor::TaskType taskType)
1161 {
1162     auto context = GetContext();
1163     CHECK_NULL_VOID(context);
1164     context->PostAsyncEvent(std::move(task), taskType);
1165 }
1166 
UpdateLayoutConstraint(const MeasureProperty & calcLayoutConstraint)1167 void FrameNode::UpdateLayoutConstraint(const MeasureProperty& calcLayoutConstraint)
1168 {
1169     layoutProperty_->UpdateCalcLayoutProperty(calcLayoutConstraint);
1170 }
1171 
RebuildRenderContextTree()1172 void FrameNode::RebuildRenderContextTree()
1173 {
1174     if (!needSyncRenderTree_) {
1175         return;
1176     }
1177     frameChildren_.clear();
1178     std::list<RefPtr<FrameNode>> children;
1179     // generate full children list, including disappear children.
1180     GenerateOneDepthVisibleFrameWithTransition(children);
1181     if (overlayNode_) {
1182         children.push_back(overlayNode_);
1183     }
1184     for (const auto& child : children) {
1185         frameChildren_.emplace(child);
1186     }
1187     renderContext_->RebuildFrame(this, children);
1188     pattern_->OnRebuildFrame();
1189     needSyncRenderTree_ = false;
1190 }
1191 
MarkModifyDone()1192 void FrameNode::MarkModifyDone()
1193 {
1194     pattern_->OnModifyDone();
1195     // restore info will overwrite the first setted attribute
1196     if (!isRestoreInfoUsed_) {
1197         isRestoreInfoUsed_ = true;
1198         auto pipeline = PipelineContext::GetCurrentContext();
1199         int32_t restoreId = GetRestoreId();
1200         if (pipeline && restoreId >= 0) {
1201             // store distribute node
1202             pipeline->StoreNode(restoreId, AceType::WeakClaim(this));
1203             // restore distribute node info
1204             std::string restoreInfo;
1205             if (pipeline->GetRestoreInfo(restoreId, restoreInfo)) {
1206                 pattern_->OnRestoreInfo(restoreInfo);
1207             }
1208         }
1209     }
1210     eventHub_->MarkModifyDone();
1211     if (IsResponseRegion() || HasPositionProp()) {
1212         auto parent = GetParent();
1213         while (parent) {
1214             auto frameNode = AceType::DynamicCast<FrameNode>(parent);
1215             if (frameNode) {
1216                 frameNode->MarkResponseRegion(true);
1217             }
1218             parent = parent->GetParent();
1219         }
1220     }
1221     renderContext_->OnModifyDone();
1222 }
1223 
OnMountToParentDone()1224 void FrameNode::OnMountToParentDone()
1225 {
1226     pattern_->OnMountToParentDone();
1227 }
1228 
FlushUpdateAndMarkDirty()1229 void FrameNode::FlushUpdateAndMarkDirty()
1230 {
1231     MarkDirtyNode();
1232 }
1233 
MarkDirtyNode(PropertyChangeFlag extraFlag)1234 void FrameNode::MarkDirtyNode(PropertyChangeFlag extraFlag)
1235 {
1236     MarkDirtyNode(IsMeasureBoundary(), IsRenderBoundary(), extraFlag);
1237 }
1238 
GetAncestorNodeOfFrame() const1239 RefPtr<FrameNode> FrameNode::GetAncestorNodeOfFrame() const
1240 {
1241     auto parent = GetParent();
1242     while (parent) {
1243         if (InstanceOf<FrameNode>(parent)) {
1244             return DynamicCast<FrameNode>(parent);
1245         }
1246         parent = parent->GetParent();
1247     }
1248     return nullptr;
1249 }
1250 
MarkNeedRenderOnly()1251 void FrameNode::MarkNeedRenderOnly()
1252 {
1253     MarkNeedRender(IsRenderBoundary());
1254 }
1255 
MarkNeedRender(bool isRenderBoundary)1256 void FrameNode::MarkNeedRender(bool isRenderBoundary)
1257 {
1258     auto context = GetContext();
1259     CHECK_NULL_VOID(context);
1260     // If it has dirtyLayoutBox, need to mark dirty after layout done.
1261     paintProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_RENDER);
1262     if (isRenderDirtyMarked_ || isLayoutDirtyMarked_) {
1263         LOGD("this node has already mark dirty, %{public}s, %{public}d, %{public}d", GetTag().c_str(),
1264             isRenderDirtyMarked_, isLayoutDirtyMarked_);
1265         return;
1266     }
1267     isRenderDirtyMarked_ = true;
1268     if (isRenderBoundary) {
1269         context->AddDirtyRenderNode(Claim(this));
1270         return;
1271     }
1272     auto parent = GetAncestorNodeOfFrame();
1273     if (parent) {
1274         parent->MarkDirtyNode(PROPERTY_UPDATE_RENDER_BY_CHILD_REQUEST);
1275     }
1276 }
1277 
MarkDirtyNode(bool isMeasureBoundary,bool isRenderBoundary,PropertyChangeFlag extraFlag)1278 void FrameNode::MarkDirtyNode(bool isMeasureBoundary, bool isRenderBoundary, PropertyChangeFlag extraFlag)
1279 {
1280     if (CheckNeedRender(extraFlag)) {
1281         paintProperty_->UpdatePropertyChangeFlag(extraFlag);
1282     }
1283     layoutProperty_->UpdatePropertyChangeFlag(extraFlag);
1284     paintProperty_->UpdatePropertyChangeFlag(extraFlag);
1285     auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
1286     auto paintFlag = paintProperty_->GetPropertyChangeFlag();
1287     if (CheckNoChanged(layoutFlag | paintFlag)) {
1288         LOGD("MarkDirtyNode: flag not changed, node tag: %{public}s", GetTag().c_str());
1289         return;
1290     }
1291     auto context = GetContext();
1292     CHECK_NULL_VOID(context);
1293 
1294     if (CheckNeedRequestMeasureAndLayout(layoutFlag)) {
1295         if (!isMeasureBoundary && IsNeedRequestParentMeasure()) {
1296             auto parent = GetAncestorNodeOfFrame();
1297             if (parent) {
1298                 parent->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1299                 return;
1300             }
1301         }
1302         if (isLayoutDirtyMarked_) {
1303             LOGD("MarkDirtyNode: isLayoutDirtyMarked is true");
1304             return;
1305         }
1306         isLayoutDirtyMarked_ = true;
1307         context->AddDirtyLayoutNode(Claim(this));
1308         return;
1309     }
1310     layoutProperty_->CleanDirty();
1311     MarkNeedRender(isRenderBoundary);
1312 }
1313 
IsNeedRequestParentMeasure() const1314 bool FrameNode::IsNeedRequestParentMeasure() const
1315 {
1316     auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
1317     if (layoutFlag == PROPERTY_UPDATE_BY_CHILD_REQUEST) {
1318         const auto& calcLayoutConstraint = layoutProperty_->GetCalcLayoutConstraint();
1319         if (calcLayoutConstraint && calcLayoutConstraint->selfIdealSize &&
1320             calcLayoutConstraint->selfIdealSize->IsValid()) {
1321             LOGD("make self measure boundary");
1322             return false;
1323         }
1324     }
1325     return CheckNeedRequestParentMeasure(layoutFlag);
1326 }
1327 
OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & visibleList)1328 void FrameNode::OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& visibleList)
1329 {
1330     if (isActive_ && IsVisible()) {
1331         visibleList.emplace_back(Claim(this));
1332     }
1333 }
1334 
OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>> & allList)1335 void FrameNode::OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>>& allList)
1336 {
1337     allList.emplace_back(Claim(this));
1338 }
1339 
OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>> & visibleList)1340 void FrameNode::OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>>& visibleList)
1341 {
1342     auto context = GetRenderContext();
1343     CHECK_NULL_VOID(context);
1344     // skip if 1.not active or 2.not visible and has no transition out animation.
1345     if (!isActive_ || (!IsVisible() && !context->HasTransitionOutAnimation())) {
1346         return;
1347     }
1348     visibleList.emplace_back(Claim(this));
1349 }
1350 
IsMeasureBoundary()1351 bool FrameNode::IsMeasureBoundary()
1352 {
1353     return isMeasureBoundary_ || pattern_->IsMeasureBoundary();
1354 }
1355 
IsRenderBoundary()1356 bool FrameNode::IsRenderBoundary()
1357 {
1358     return pattern_->IsRenderBoundary();
1359 }
1360 
GetPattern() const1361 const RefPtr<Pattern>& FrameNode::GetPattern() const
1362 {
1363     return pattern_;
1364 }
1365 
IsAtomicNode() const1366 bool FrameNode::IsAtomicNode() const
1367 {
1368     return pattern_->IsAtomicNode();
1369 }
1370 
GetHitTestMode() const1371 HitTestMode FrameNode::GetHitTestMode() const
1372 {
1373     auto gestureHub = eventHub_->GetGestureEventHub();
1374     return gestureHub ? gestureHub->GetHitTestMode() : HitTestMode::HTMDEFAULT;
1375 }
1376 
SetHitTestMode(HitTestMode mode)1377 void FrameNode::SetHitTestMode(HitTestMode mode)
1378 {
1379     auto gestureHub = eventHub_->GetOrCreateGestureEventHub();
1380     CHECK_NULL_VOID(gestureHub);
1381     gestureHub->SetHitTestMode(mode);
1382 }
1383 
GetTouchable() const1384 bool FrameNode::GetTouchable() const
1385 {
1386     auto gestureHub = eventHub_->GetGestureEventHub();
1387     return gestureHub ? gestureHub->GetTouchable() : true;
1388 }
1389 
IsResponseRegion() const1390 bool FrameNode::IsResponseRegion() const
1391 {
1392     auto renderContext = GetRenderContext();
1393     CHECK_NULL_RETURN(renderContext, false);
1394     auto clip = renderContext->GetClipEdge().value_or(false);
1395     if (clip) {
1396         return false;
1397     }
1398     auto gestureHub = eventHub_->GetGestureEventHub();
1399     return gestureHub ? gestureHub->IsResponseRegion() : false;
1400 }
1401 
MarkResponseRegion(bool isResponseRegion)1402 void FrameNode::MarkResponseRegion(bool isResponseRegion)
1403 {
1404     auto gestureHub = eventHub_->GetOrCreateGestureEventHub();
1405     if (gestureHub) {
1406         gestureHub->MarkResponseRegion(isResponseRegion);
1407     }
1408 }
1409 
GetPaintRectWithTransform() const1410 RectF FrameNode::GetPaintRectWithTransform() const
1411 {
1412     return renderContext_->GetPaintRectWithTransform();
1413 }
1414 
GetTransformScale() const1415 VectorF FrameNode::GetTransformScale() const
1416 {
1417     return renderContext_->GetTransformScaleValue({ 1.0f, 1.0f });
1418 }
1419 
IsOutOfTouchTestRegion(const PointF & parentRevertPoint,int32_t sourceType)1420 bool FrameNode::IsOutOfTouchTestRegion(const PointF& parentRevertPoint, int32_t sourceType)
1421 {
1422     bool isInChildRegion = false;
1423     auto paintRect = renderContext_->GetPaintRectWithoutTransform();
1424     auto responseRegionList = GetResponseRegionList(paintRect, sourceType);
1425     auto renderContext = GetRenderContext();
1426     CHECK_NULL_RETURN(renderContext, false);
1427 
1428     auto revertPoint = parentRevertPoint;
1429     renderContext->GetPointWithRevert(revertPoint);
1430     auto subRevertPoint = revertPoint - paintRect.GetOffset();
1431     auto clip = renderContext->GetClipEdge().value_or(false);
1432     if (!InResponseRegionList(revertPoint, responseRegionList) || !GetTouchable()) {
1433         if (clip) {
1434             if (SystemProperties::GetDebugEnabled()) {
1435                 LOGI("TouchTest: frameNode use clip, point is out of region in %{public}s", GetTag().c_str());
1436             }
1437             return true;
1438         }
1439         for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
1440             const auto& child = iter->Upgrade();
1441             if (child && !child->IsOutOfTouchTestRegion(subRevertPoint, sourceType)) {
1442                 if (SystemProperties::GetDebugEnabled()) {
1443                     LOGI("TouchTest: point is out of region in %{public}s, but is in child region", GetTag().c_str());
1444                 }
1445                 isInChildRegion = true;
1446                 break;
1447             }
1448         }
1449         if (!isInChildRegion) {
1450             if (SystemProperties::GetDebugEnabled()) {
1451                 LOGI("TouchTest: point is out of region in %{public}s", GetTag().c_str());
1452             }
1453             return true;
1454         }
1455     }
1456     return false;
1457 }
1458 
TouchTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,const TouchRestrict & touchRestrict,TouchTestResult & result,int32_t touchId)1459 HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& parentLocalPoint,
1460     const PointF& parentRevertPoint, const TouchRestrict& touchRestrict, TouchTestResult& result, int32_t touchId)
1461 {
1462     if (!isActive_ || !eventHub_->IsEnabled() || bypass_) {
1463         if (SystemProperties::GetDebugEnabled()) {
1464             LOGI("%{public}s is inActive, need't do touch test", GetTag().c_str());
1465         }
1466         return HitTestResult::OUT_OF_REGION;
1467     }
1468     auto& translateIds = NGGestureRecognizer::GetGlobalTransIds();
1469     auto& translateCfg = NGGestureRecognizer::GetGlobalTransCfg();
1470     auto paintRect = renderContext_->GetPaintRectWithTransform();
1471     auto origRect = renderContext_->GetPaintRectWithoutTransform();
1472     auto param = renderContext_->GetTrans();
1473     if (param.empty()) {
1474         translateCfg[GetId()] = { .id = GetId() };
1475     } else {
1476         translateCfg[GetId()] = { param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7],
1477             param[8], GetId() };
1478     }
1479     auto parent = GetAncestorNodeOfFrame();
1480     if (parent) {
1481         AncestorNodeInfo ancestorNodeInfo { parent->GetId() };
1482         translateIds[GetId()] = ancestorNodeInfo;
1483     }
1484 
1485     auto responseRegionList = GetResponseRegionList(origRect, static_cast<int32_t>(touchRestrict.sourceType));
1486     if (SystemProperties::GetDebugEnabled()) {
1487         LOGI("TouchTest: point is %{public}s in %{public}s, depth: %{public}d", parentRevertPoint.ToString().c_str(),
1488             GetTag().c_str(), GetDepth());
1489         for (const auto& rect : responseRegionList) {
1490             LOGI("TouchTest: responseRegionList is %{public}s, point is %{public}s", rect.ToString().c_str(),
1491                 parentRevertPoint.ToString().c_str());
1492         }
1493     }
1494     {
1495         ACE_DEBUG_SCOPED_TRACE("FrameNode::IsOutOfTouchTestRegion");
1496         if (IsOutOfTouchTestRegion(parentRevertPoint, static_cast<int32_t>(touchRestrict.sourceType))) {
1497             return HitTestResult::OUT_OF_REGION;
1498         }
1499     }
1500 
1501     HitTestResult testResult = HitTestResult::OUT_OF_REGION;
1502     bool preventBubbling = false;
1503     // Child nodes are repackaged into gesture groups (parallel gesture groups, exclusive gesture groups, etc.)
1504     // based on the gesture attributes set by the current parent node (high and low priority, parallel gestures,
1505     // etc.), the newComingTargets is the template object to collect child nodes gesture and used by gestureHub to
1506     // pack gesture group.
1507     TouchTestResult newComingTargets;
1508     auto tmp = parentLocalPoint - paintRect.GetOffset();
1509     auto preLocation = tmp;
1510     renderContext_->GetPointWithTransform(tmp);
1511     const auto localPoint = tmp;
1512     auto localTransformOffset = preLocation - localPoint;
1513 
1514     auto revertPoint = parentRevertPoint;
1515     renderContext_->GetPointWithRevert(revertPoint);
1516     auto subRevertPoint = revertPoint - origRect.GetOffset();
1517     bool consumed = false;
1518     for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
1519         if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
1520             break;
1521         }
1522 
1523         const auto& child = iter->Upgrade();
1524         if (!child) {
1525             continue;
1526         }
1527         auto childHitResult = child->TouchTest(globalPoint, localPoint, subRevertPoint, touchRestrict,
1528             newComingTargets, touchId);
1529         if (childHitResult == HitTestResult::STOP_BUBBLING) {
1530             preventBubbling = true;
1531             consumed = true;
1532             if ((child->GetHitTestMode() == HitTestMode::HTMBLOCK) ||
1533                 (child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
1534                 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
1535                 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && IsExclusiveEventForChild())) {
1536                 break;
1537             }
1538         }
1539 
1540         // In normal process, the node block the brother node.
1541         if (childHitResult == HitTestResult::BUBBLING &&
1542             ((child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
1543                 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
1544                 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && IsExclusiveEventForChild()))) {
1545             consumed = true;
1546             break;
1547         }
1548     }
1549 
1550     // first update HitTestResult by children status.
1551     if (consumed) {
1552         testResult = preventBubbling ? HitTestResult::STOP_BUBBLING : HitTestResult::BUBBLING;
1553         consumed = false;
1554     } else if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
1555         testResult = HitTestResult::STOP_BUBBLING;
1556     }
1557 
1558     if (!preventBubbling && (GetHitTestMode() != HitTestMode::HTMNONE) &&
1559         (InResponseRegionList(revertPoint, responseRegionList))) {
1560         pattern_->OnTouchTestHit(touchRestrict.hitTestType);
1561         consumed = true;
1562         if (touchRestrict.hitTestType == SourceType::TOUCH) {
1563             auto gestureHub = eventHub_->GetGestureEventHub();
1564             if (gestureHub) {
1565                 TouchTestResult finalResult;
1566                 const auto coordinateOffset = globalPoint - localPoint - localTransformOffset;
1567                 preventBubbling = gestureHub->ProcessTouchTestHit(
1568                     coordinateOffset, touchRestrict, newComingTargets, finalResult, touchId, localPoint);
1569                 newComingTargets.swap(finalResult);
1570             }
1571         } else if (touchRestrict.hitTestType == SourceType::MOUSE) {
1572             auto mouseHub = eventHub_->GetInputEventHub();
1573             if (mouseHub) {
1574                 const auto coordinateOffset = globalPoint - localPoint;
1575                 preventBubbling = mouseHub->ProcessMouseTestHit(coordinateOffset, newComingTargets);
1576             }
1577         }
1578     }
1579 
1580     result.splice(result.end(), std::move(newComingTargets));
1581     if (touchRestrict.hitTestType == SourceType::TOUCH) {
1582         // combine into exclusive recognizer group.
1583         auto gestureHub = eventHub_->GetGestureEventHub();
1584         if (gestureHub) {
1585             gestureHub->CombineIntoExclusiveRecognizer(globalPoint, localPoint, result, touchId);
1586         }
1587     }
1588 
1589     // consumed by children and return result.
1590     if (!consumed) {
1591         return testResult;
1592     }
1593 
1594     if (testResult == HitTestResult::OUT_OF_REGION) {
1595         // consume only by self.
1596         if (preventBubbling) {
1597             return HitTestResult::STOP_BUBBLING;
1598         }
1599         return (GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ? HitTestResult::SELF_TRANSPARENT
1600                                                                       : HitTestResult::BUBBLING;
1601     }
1602     // consume by self and children.
1603     return testResult;
1604 }
1605 
GetResponseRegionList(const RectF & rect,int32_t sourceType)1606 std::vector<RectF> FrameNode::GetResponseRegionList(const RectF& rect, int32_t sourceType)
1607 {
1608     std::vector<RectF> responseRegionList;
1609     auto gestureHub = eventHub_->GetGestureEventHub();
1610     if (!gestureHub) {
1611         responseRegionList.emplace_back(rect);
1612         return responseRegionList;
1613     }
1614     auto scaleProperty = ScaleProperty::CreateScaleProperty();
1615     bool isMouseEvent = (static_cast<SourceType>(sourceType) == SourceType::MOUSE);
1616     if (isMouseEvent) {
1617         if (gestureHub->GetResponseRegion().empty() && (gestureHub->GetMouseResponseRegion().empty())) {
1618             responseRegionList.emplace_back(rect);
1619             return responseRegionList;
1620         }
1621     } else {
1622         if (gestureHub->GetResponseRegion().empty()) {
1623             responseRegionList.emplace_back(rect);
1624             return responseRegionList;
1625         }
1626     }
1627 
1628     if (isMouseEvent && (!gestureHub->GetMouseResponseRegion().empty())) {
1629         for (const auto& region : gestureHub->GetMouseResponseRegion()) {
1630             auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
1631             auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
1632             auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
1633             auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
1634             RectF mouseRegion(rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(),
1635                 height.value());
1636             responseRegionList.emplace_back(mouseRegion);
1637         }
1638         return responseRegionList;
1639     }
1640     for (const auto& region : gestureHub->GetResponseRegion()) {
1641         auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
1642         auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
1643         auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
1644         auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
1645         RectF responseRegion(
1646             rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(), height.value());
1647         responseRegionList.emplace_back(responseRegion);
1648     }
1649     return responseRegionList;
1650 }
1651 
InResponseRegionList(const PointF & parentLocalPoint,const std::vector<RectF> & responseRegionList) const1652 bool FrameNode::InResponseRegionList(const PointF& parentLocalPoint, const std::vector<RectF>& responseRegionList) const
1653 {
1654     for (const auto& rect : responseRegionList) {
1655         if (rect.IsInRegion(parentLocalPoint)) {
1656             return true;
1657         }
1658     }
1659     return false;
1660 }
1661 
MouseTest(const PointF & globalPoint,const PointF & parentLocalPoint,MouseTestResult & onMouseResult,MouseTestResult & onHoverResult,RefPtr<FrameNode> & hoverNode)1662 HitTestResult FrameNode::MouseTest(const PointF& globalPoint, const PointF& parentLocalPoint,
1663     MouseTestResult& onMouseResult, MouseTestResult& onHoverResult, RefPtr<FrameNode>& hoverNode)
1664 {
1665     // unuseable function. do nothing.
1666     return HitTestResult::BUBBLING;
1667 }
1668 
AxisTest(const PointF & globalPoint,const PointF & parentLocalPoint,AxisTestResult & onAxisResult)1669 HitTestResult FrameNode::AxisTest(
1670     const PointF& globalPoint, const PointF& parentLocalPoint, AxisTestResult& onAxisResult)
1671 {
1672     const auto& rect = renderContext_->GetPaintRectWithTransform();
1673     LOGD("AxisTest: type is %{public}s, the region is %{public}lf, %{public}lf, %{public}lf, %{public}lf",
1674         GetTag().c_str(), rect.Left(), rect.Top(), rect.Width(), rect.Height());
1675     // TODO: disableTouchEvent || disabled_ need handle
1676 
1677     // TODO: Region need change to RectList
1678     if (!rect.IsInRegion(parentLocalPoint)) {
1679         return HitTestResult::OUT_OF_REGION;
1680     }
1681 
1682     bool preventBubbling = false;
1683 
1684     const auto localPoint = parentLocalPoint - rect.GetOffset();
1685     const auto& children = GetChildren();
1686     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
1687         auto& child = *iter;
1688         auto childHitResult = child->AxisTest(globalPoint, localPoint, onAxisResult);
1689         if (childHitResult == HitTestResult::STOP_BUBBLING) {
1690             preventBubbling = true;
1691         }
1692         // In normal process, the node block the brother node.
1693         if (childHitResult == HitTestResult::BUBBLING) {
1694             // TODO: add hit test mode judge.
1695             break;
1696         }
1697     }
1698 
1699     AxisTestResult axisResult;
1700     bool isPrevent = false;
1701     auto inputHub = eventHub_->GetInputEventHub();
1702     if (inputHub) {
1703         const auto coordinateOffset = globalPoint - localPoint;
1704         isPrevent = inputHub->ProcessAxisTestHit(coordinateOffset, axisResult);
1705     }
1706 
1707     if (!preventBubbling) {
1708         preventBubbling = isPrevent;
1709         onAxisResult.splice(onAxisResult.end(), std::move(axisResult));
1710     }
1711     if (preventBubbling) {
1712         return HitTestResult::STOP_BUBBLING;
1713     }
1714     return HitTestResult::BUBBLING;
1715 }
1716 
AnimateHoverEffect(bool isHovered) const1717 void FrameNode::AnimateHoverEffect(bool isHovered) const
1718 {
1719     auto renderContext = GetRenderContext();
1720     if (!renderContext) {
1721         return;
1722     }
1723     HoverEffectType animationType = HoverEffectType::UNKNOWN;
1724     auto inputEventHub = eventHub_->GetInputEventHub();
1725     if (inputEventHub) {
1726         animationType = inputEventHub->GetHoverEffect();
1727         if (animationType == HoverEffectType::UNKNOWN || animationType == HoverEffectType::AUTO) {
1728             animationType = inputEventHub->GetHoverEffectAuto();
1729         }
1730     }
1731     if (animationType == HoverEffectType::SCALE) {
1732         renderContext->AnimateHoverEffectScale(isHovered);
1733     } else if (animationType == HoverEffectType::BOARD) {
1734         renderContext->AnimateHoverEffectBoard(isHovered);
1735     }
1736 }
1737 
GetOrCreateFocusHub() const1738 RefPtr<FocusHub> FrameNode::GetOrCreateFocusHub() const
1739 {
1740     if (!pattern_) {
1741         return eventHub_->GetOrCreateFocusHub();
1742     }
1743     auto focusPattern = pattern_->GetFocusPattern();
1744     return eventHub_->GetOrCreateFocusHub(focusPattern.GetFocusType(), focusPattern.GetFocusable(),
1745         focusPattern.GetStyleType(), focusPattern.GetFocusPaintParams());
1746 }
1747 
OnWindowShow()1748 void FrameNode::OnWindowShow()
1749 {
1750     pattern_->OnWindowShow();
1751 }
1752 
OnWindowHide()1753 void FrameNode::OnWindowHide()
1754 {
1755     pattern_->OnWindowHide();
1756 }
1757 
OnWindowFocused()1758 void FrameNode::OnWindowFocused()
1759 {
1760     pattern_->OnWindowFocused();
1761 }
1762 
OnWindowUnfocused()1763 void FrameNode::OnWindowUnfocused()
1764 {
1765     pattern_->OnWindowUnfocused();
1766 }
1767 
ContextPositionConvertToPX(const RefPtr<RenderContext> & context,const SizeF & percentReference) const1768 std::pair<float, float> FrameNode::ContextPositionConvertToPX(
1769     const RefPtr<RenderContext>& context, const SizeF& percentReference) const
1770 {
1771     std::pair<float, float> position;
1772     CHECK_NULL_RETURN_NOLOG(context, position);
1773     auto scaleProperty = ScaleProperty::CreateScaleProperty();
1774     position.first =
1775         ConvertToPx(context->GetPositionProperty()->GetPosition()->GetX(), scaleProperty, percentReference.Width())
1776             .value_or(0.0);
1777     position.second =
1778         ConvertToPx(context->GetPositionProperty()->GetPosition()->GetY(), scaleProperty, percentReference.Height())
1779             .value_or(0.0);
1780     return position;
1781 }
1782 
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)1783 void FrameNode::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
1784 {
1785     pattern_->OnWindowSizeChanged(width, height, type);
1786 }
1787 
GetOffsetRelativeToWindow() const1788 OffsetF FrameNode::GetOffsetRelativeToWindow() const
1789 {
1790     auto offset = geometryNode_->GetFrameOffset();
1791     auto parent = GetAncestorNodeOfFrame();
1792     if (renderContext_ && renderContext_->GetPositionProperty()) {
1793         if (renderContext_->GetPositionProperty()->HasPosition()) {
1794             auto renderPosition =
1795                 ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
1796             offset.SetX(static_cast<float>(renderPosition.first));
1797             offset.SetY(static_cast<float>(renderPosition.second));
1798         }
1799     }
1800     while (parent) {
1801         auto parentRenderContext = parent->GetRenderContext();
1802         if (parentRenderContext && parentRenderContext->GetPositionProperty()) {
1803             if (parentRenderContext->GetPositionProperty()->HasPosition()) {
1804                 auto parentLayoutProperty = parent->GetLayoutProperty();
1805                 CHECK_NULL_RETURN_NOLOG(parentLayoutProperty, offset);
1806                 auto parentRenderContextPosition = ContextPositionConvertToPX(
1807                     parentRenderContext, parentLayoutProperty->GetLayoutConstraint()->percentReference);
1808                 offset.AddX(static_cast<float>(parentRenderContextPosition.first));
1809                 offset.AddY(static_cast<float>(parentRenderContextPosition.second));
1810                 parent = parent->GetAncestorNodeOfFrame();
1811                 continue;
1812             }
1813         }
1814 
1815         offset += parent->geometryNode_->GetFrameOffset();
1816         parent = parent->GetAncestorNodeOfFrame();
1817     }
1818 
1819     return offset;
1820 }
1821 
GetTransformRectRelativeToWindow() const1822 RectF FrameNode::GetTransformRectRelativeToWindow() const
1823 {
1824     auto context = GetRenderContext();
1825     CHECK_NULL_RETURN(context, RectF());
1826     RectF rect = context->GetPaintRectWithTransform();
1827     auto offset = rect.GetOffset();
1828     auto parent = GetAncestorNodeOfFrame();
1829     while (parent) {
1830         auto parentRenderContext = parent->GetRenderContext();
1831         CHECK_NULL_RETURN(parentRenderContext, rect);
1832         auto parentScale = parentRenderContext->GetTransformScale();
1833         if (parentScale) {
1834             auto oldSize = rect.GetSize();
1835             auto newSize = SizeF(oldSize.Width() * parentScale.value().x, oldSize.Height() * parentScale.value().y);
1836             rect.SetSize(newSize);
1837 
1838             offset = OffsetF(offset.GetX() * parentScale.value().x, offset.GetY() * parentScale.value().y);
1839         }
1840 
1841         offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
1842 
1843         parent = parent->GetAncestorNodeOfFrame();
1844     }
1845     rect.SetOffset(offset);
1846     return rect;
1847 }
1848 
GetTransformRelativeOffset() const1849 OffsetF FrameNode::GetTransformRelativeOffset() const
1850 {
1851     auto context = GetRenderContext();
1852     CHECK_NULL_RETURN(context, OffsetF());
1853     auto offset = context->GetPaintRectWithTransform().GetOffset();
1854     auto parent = GetAncestorNodeOfFrame();
1855 
1856     while (parent) {
1857         auto parentRenderContext = parent->GetRenderContext();
1858         offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
1859         parent = parent->GetAncestorNodeOfFrame();
1860     }
1861 
1862     return offset;
1863 }
1864 
GetPaintRectOffset(bool excludeSelf) const1865 OffsetF FrameNode::GetPaintRectOffset(bool excludeSelf) const
1866 {
1867     auto context = GetRenderContext();
1868     CHECK_NULL_RETURN(context, OffsetF());
1869     OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithTransform().GetOffset();
1870     auto parent = GetAncestorNodeOfFrame();
1871     while (parent) {
1872         auto renderContext = parent->GetRenderContext();
1873         CHECK_NULL_RETURN(renderContext, OffsetF());
1874         offset += renderContext->GetPaintRectWithTransform().GetOffset();
1875         parent = parent->GetAncestorNodeOfFrame();
1876     }
1877     return offset;
1878 }
1879 
GetParentGlobalOffsetDuringLayout() const1880 OffsetF FrameNode::GetParentGlobalOffsetDuringLayout() const
1881 {
1882     OffsetF offset {};
1883     auto parent = GetAncestorNodeOfFrame();
1884     while (parent) {
1885         offset += parent->geometryNode_->GetFrameOffset();
1886         parent = parent->GetAncestorNodeOfFrame();
1887     }
1888     return offset;
1889 }
1890 
GetPaintRectGlobalOffsetWithTranslate(bool excludeSelf) const1891 OffsetF FrameNode::GetPaintRectGlobalOffsetWithTranslate(bool excludeSelf) const
1892 {
1893     auto context = GetRenderContext();
1894     CHECK_NULL_RETURN(context, OffsetF());
1895     OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithTranslate().GetOffset();
1896     auto parent = GetAncestorNodeOfFrame();
1897     while (parent) {
1898         auto renderContext = parent->GetRenderContext();
1899         CHECK_NULL_RETURN(renderContext, OffsetF());
1900         offset += renderContext->GetPaintRectWithTranslate().GetOffset();
1901         parent = parent->GetAncestorNodeOfFrame();
1902     }
1903     return offset;
1904 }
1905 
GetPaintRectOffsetToPage() const1906 OffsetF FrameNode::GetPaintRectOffsetToPage() const
1907 {
1908     auto context = GetRenderContext();
1909     CHECK_NULL_RETURN(context, OffsetF());
1910     OffsetF offset = context->GetPaintRectWithTransform().GetOffset();
1911     auto parent = GetAncestorNodeOfFrame();
1912     while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
1913         auto renderContext = parent->GetRenderContext();
1914         CHECK_NULL_RETURN(renderContext, OffsetF());
1915         offset += renderContext->GetPaintRectWithTransform().GetOffset();
1916         parent = parent->GetAncestorNodeOfFrame();
1917     }
1918     return (parent && parent->GetTag() == V2::PAGE_ETS_TAG) ? offset : OffsetF();
1919 }
1920 
GetViewPort() const1921 std::optional<RectF> FrameNode::GetViewPort() const
1922 {
1923     if (viewPort_.has_value()) {
1924         return viewPort_;
1925     }
1926     auto parent = GetAncestorNodeOfFrame();
1927     while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
1928         auto parentViewPort = parent->GetSelfViewPort();
1929         if (parentViewPort.has_value()) {
1930             return parentViewPort;
1931         }
1932         parent = parent->GetAncestorNodeOfFrame();
1933     }
1934     return std::nullopt;
1935 }
1936 
OnNotifyMemoryLevel(int32_t level)1937 void FrameNode::OnNotifyMemoryLevel(int32_t level)
1938 {
1939     pattern_->OnNotifyMemoryLevel(level);
1940 }
1941 
GetAllDepthChildrenCount()1942 int32_t FrameNode::GetAllDepthChildrenCount()
1943 {
1944     int32_t result = 0;
1945     std::list<RefPtr<FrameNode>> children;
1946     children.emplace_back(Claim(this));
1947     while (!children.empty()) {
1948         auto& node = children.front();
1949         if (!node->IsInternal()) {
1950             result++;
1951             node->GenerateOneDepthVisibleFrame(children);
1952         }
1953         children.pop_front();
1954     }
1955     return result;
1956 }
1957 
OnAccessibilityEvent(AccessibilityEventType eventType,WindowsContentChangeTypes windowsContentChangeType) const1958 void FrameNode::OnAccessibilityEvent(
1959     AccessibilityEventType eventType, WindowsContentChangeTypes windowsContentChangeType) const
1960 {
1961     if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
1962         AccessibilityEvent event;
1963         event.type = eventType;
1964         event.windowContentChangeTypes = windowsContentChangeType;
1965         event.nodeId = GetAccessibilityId();
1966         auto pipeline = PipelineContext::GetCurrentContext();
1967         CHECK_NULL_VOID(pipeline);
1968         pipeline->SendEventToAccessibility(event);
1969     }
1970 }
1971 
OnAccessibilityEvent(AccessibilityEventType eventType,std::string beforeText,std::string latestContent) const1972 void FrameNode::OnAccessibilityEvent(
1973     AccessibilityEventType eventType, std::string beforeText, std::string latestContent) const
1974 {
1975     if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
1976         AccessibilityEvent event;
1977         event.type = eventType;
1978         event.nodeId = GetAccessibilityId();
1979         event.beforeText = beforeText;
1980         event.latestContent = latestContent;
1981         auto pipeline = PipelineContext::GetCurrentContext();
1982         CHECK_NULL_VOID(pipeline);
1983         pipeline->SendEventToAccessibility(event);
1984     }
1985 }
1986 
MarkRemoving()1987 bool FrameNode::MarkRemoving()
1988 {
1989     bool pendingRemove = false;
1990     if (!layoutProperty_ || !geometryNode_) {
1991         return pendingRemove;
1992     }
1993 
1994     isRemoving_ = true;
1995 
1996     const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
1997     if (geometryTransition != nullptr) {
1998         geometryTransition->Build(WeakClaim(this), false);
1999         pendingRemove = true;
2000     }
2001 
2002     const auto& children = GetChildren();
2003     for (const auto& child : children) {
2004         pendingRemove = child->MarkRemoving() || pendingRemove;
2005     }
2006     return pendingRemove;
2007 }
2008 
AddHotZoneRect(const DimensionRect & hotZoneRect) const2009 void FrameNode::AddHotZoneRect(const DimensionRect& hotZoneRect) const
2010 {
2011     auto gestureHub = GetOrCreateGestureEventHub();
2012     gestureHub->AddResponseRect(hotZoneRect);
2013 }
2014 
RemoveLastHotZoneRect() const2015 void FrameNode::RemoveLastHotZoneRect() const
2016 {
2017     auto gestureHub = GetOrCreateGestureEventHub();
2018     gestureHub->RemoveLastResponseRect();
2019 }
2020 
OnRemoveFromParent(bool allowTransition)2021 bool FrameNode::OnRemoveFromParent(bool allowTransition)
2022 {
2023     // kick out transition animation if needed, wont re-entry if already detached.
2024     DetachFromMainTree(!allowTransition);
2025     auto context = GetRenderContext();
2026     CHECK_NULL_RETURN(context, false);
2027     if (!allowTransition || RemoveImmediately()) {
2028         // directly remove, reset focusHub, parent and depth
2029         if (auto focusHub = GetFocusHub()) {
2030             focusHub->RemoveSelf();
2031         }
2032         ResetParent();
2033         return true;
2034     }
2035     // delayed remove, will move self into disappearing children
2036     return false;
2037 }
2038 
FindChildByPosition(float x,float y)2039 RefPtr<FrameNode> FrameNode::FindChildByPosition(float x, float y)
2040 {
2041     std::map<int32_t, RefPtr<FrameNode>> hitFrameNodes;
2042     std::list<RefPtr<FrameNode>> children;
2043     GenerateOneDepthAllFrame(children);
2044     for (const auto& child : children) {
2045         auto geometryNode = child->GetGeometryNode();
2046         if (!geometryNode) {
2047             continue;
2048         }
2049 
2050         auto globalFrameRect = geometryNode->GetFrameRect();
2051         globalFrameRect.SetOffset(child->GetOffsetRelativeToWindow());
2052 
2053         if (globalFrameRect.IsInRegion(PointF(x, y))) {
2054             hitFrameNodes.insert(std::make_pair(child->GetDepth(), child));
2055         }
2056     }
2057 
2058     if (hitFrameNodes.empty()) {
2059         return nullptr;
2060     }
2061 
2062     return hitFrameNodes.rbegin()->second;
2063 }
2064 
CreateAnimatablePropertyFloat(const std::string & propertyName,float value,const std::function<void (float)> & onCallbackEvent)2065 void FrameNode::CreateAnimatablePropertyFloat(
2066     const std::string& propertyName, float value, const std::function<void(float)>& onCallbackEvent)
2067 {
2068     auto context = GetRenderContext();
2069     CHECK_NULL_VOID(context);
2070     auto iter = nodeAnimatablePropertyMap_.find(propertyName);
2071     if (iter != nodeAnimatablePropertyMap_.end()) {
2072         LOGW("AnimatableProperty already exists!");
2073         return;
2074     }
2075     auto property = AceType::MakeRefPtr<NodeAnimatablePropertyFloat>(value, std::move(onCallbackEvent));
2076     context->AttachNodeAnimatableProperty(property);
2077     nodeAnimatablePropertyMap_.emplace(propertyName, property);
2078 }
2079 
UpdateAnimatablePropertyFloat(const std::string & propertyName,float value)2080 void FrameNode::UpdateAnimatablePropertyFloat(const std::string& propertyName, float value)
2081 {
2082     auto iter = nodeAnimatablePropertyMap_.find(propertyName);
2083     if (iter == nodeAnimatablePropertyMap_.end()) {
2084         LOGW("AnimatableProperty not exists!");
2085         return;
2086     }
2087     auto property = AceType::DynamicCast<NodeAnimatablePropertyFloat>(iter->second);
2088     CHECK_NULL_VOID(property);
2089     property->Set(value);
2090 }
2091 
CreateAnimatableArithmeticProperty(const std::string & propertyName,RefPtr<CustomAnimatableArithmetic> & value,std::function<void (const RefPtr<CustomAnimatableArithmetic> &)> & onCallbackEvent)2092 void FrameNode::CreateAnimatableArithmeticProperty(const std::string& propertyName,
2093     RefPtr<CustomAnimatableArithmetic>& value,
2094     std::function<void(const RefPtr<CustomAnimatableArithmetic>&)>& onCallbackEvent)
2095 {
2096     auto context = GetRenderContext();
2097     CHECK_NULL_VOID(context);
2098     auto iter = nodeAnimatablePropertyMap_.find(propertyName);
2099     if (iter != nodeAnimatablePropertyMap_.end()) {
2100         LOGW("AnimatableProperty already exists!");
2101         return;
2102     }
2103     auto property = AceType::MakeRefPtr<NodeAnimatableArithmeticProperty>(value, std::move(onCallbackEvent));
2104     context->AttachNodeAnimatableProperty(property);
2105     nodeAnimatablePropertyMap_.emplace(propertyName, property);
2106 }
2107 
UpdateAnimatableArithmeticProperty(const std::string & propertyName,RefPtr<CustomAnimatableArithmetic> & value)2108 void FrameNode::UpdateAnimatableArithmeticProperty(
2109     const std::string& propertyName, RefPtr<CustomAnimatableArithmetic>& value)
2110 {
2111     auto iter = nodeAnimatablePropertyMap_.find(propertyName);
2112     if (iter == nodeAnimatablePropertyMap_.end()) {
2113         LOGW("AnimatableProperty not exists!");
2114         return;
2115     }
2116     auto property = AceType::DynamicCast<NodeAnimatableArithmeticProperty>(iter->second);
2117     CHECK_NULL_VOID(property);
2118     property->Set(value);
2119 }
2120 
ProvideRestoreInfo()2121 std::string FrameNode::ProvideRestoreInfo()
2122 {
2123     return pattern_->ProvideRestoreInfo();
2124 }
2125 
RemoveImmediately() const2126 bool FrameNode::RemoveImmediately() const
2127 {
2128     auto context = GetRenderContext();
2129     CHECK_NULL_RETURN(context, true);
2130     // has transition out animation, need to wait for animation end
2131     return !context->HasTransitionOutAnimation();
2132 }
2133 
GetNodesById(const std::unordered_set<int32_t> & set)2134 std::vector<RefPtr<FrameNode>> FrameNode::GetNodesById(const std::unordered_set<int32_t>& set)
2135 {
2136     std::vector<RefPtr<FrameNode>> nodes;
2137     for (auto nodeId : set) {
2138         auto uiNode = ElementRegister::GetInstance()->GetUINodeById(nodeId);
2139         if (!uiNode) {
2140             continue;
2141         }
2142         auto frameNode = DynamicCast<FrameNode>(uiNode);
2143         if (frameNode) {
2144             nodes.emplace_back(frameNode);
2145         }
2146     }
2147     return nodes;
2148 }
2149 
AddFRCSceneInfo(const std::string & name,float speed,SceneStatus status)2150 void FrameNode::AddFRCSceneInfo(const std::string& name, float speed, SceneStatus status)
2151 {
2152     // [PLANNING]: Frame Rate Controller(FRC):
2153     // Based on scene, speed and scene status, FrameRateRange will be sent to RSNode.
2154 }
2155 
CheckSecurityComponentStatus(std::vector<RectF> & rect)2156 void FrameNode::CheckSecurityComponentStatus(std::vector<RectF>& rect)
2157 {
2158     auto paintRect = GetTransformRectRelativeToWindow();
2159     if (IsSecurityComponent()) {
2160         bypass_ = CheckRectIntersect(paintRect, rect);
2161     }
2162     for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
2163         const auto& child = iter->Upgrade();
2164         if (child) {
2165             child->CheckSecurityComponentStatus(rect);
2166         }
2167     }
2168     rect.push_back(paintRect);
2169 }
2170 
CheckRectIntersect(const RectF & dest,std::vector<RectF> & origin)2171 bool FrameNode::CheckRectIntersect(const RectF& dest, std::vector<RectF>& origin)
2172 {
2173     for (auto originRect : origin) {
2174         if (originRect.IsInnerIntersectWith(dest)) {
2175             return true;
2176         }
2177     }
2178     return false;
2179 }
2180 
HaveSecurityComponent()2181 bool FrameNode::HaveSecurityComponent()
2182 {
2183     if (IsSecurityComponent()) {
2184         return true;
2185     }
2186     for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
2187         const auto& child = iter->Upgrade();
2188         if (child && child->HaveSecurityComponent()) {
2189             return true;
2190         }
2191     }
2192     return false;
2193 }
2194 
IsSecurityComponent()2195 bool FrameNode::IsSecurityComponent()
2196 {
2197     return GetTag() == V2::LOCATION_BUTTON_ETS_TAG || GetTag() == V2::PASTE_BUTTON_ETS_TAG ||
2198            GetTag() == V2::SAVE_BUTTON_ETS_TAG;
2199 }
2200 
GetPercentSensitive()2201 void FrameNode::GetPercentSensitive()
2202 {
2203     auto res = layoutProperty_->GetPercentSensitive();
2204     if (res.first) {
2205         if (layoutAlgorithm_) {
2206             layoutAlgorithm_->SetPercentWidth(true);
2207         }
2208     }
2209     if (res.second) {
2210         if (layoutAlgorithm_) {
2211             layoutAlgorithm_->SetPercentHeight(true);
2212         }
2213     }
2214 }
2215 
UpdatePercentSensitive()2216 void FrameNode::UpdatePercentSensitive()
2217 {
2218     auto res = layoutProperty_->UpdatePercentSensitive(
2219         layoutAlgorithm_->GetPercentHeight(), layoutAlgorithm_->GetPercentWidth());
2220     if (res.first) {
2221         auto parent = GetAncestorNodeOfFrame();
2222         if (parent && parent->layoutAlgorithm_) {
2223             parent->layoutAlgorithm_->SetPercentWidth(true);
2224         }
2225     }
2226     if (res.second) {
2227         auto parent = GetAncestorNodeOfFrame();
2228         if (parent && parent->layoutAlgorithm_) {
2229             parent->layoutAlgorithm_->SetPercentHeight(true);
2230         }
2231     }
2232 }
2233 
2234 // This will call child and self measure process.
Measure(const std::optional<LayoutConstraintF> & parentConstraint)2235 void FrameNode::Measure(const std::optional<LayoutConstraintF>& parentConstraint)
2236 {
2237     if (!oldGeometryNode_) {
2238         oldGeometryNode_ = geometryNode_->Clone();
2239     }
2240     RestoreGeoState();
2241     pattern_->BeforeCreateLayoutWrapper();
2242     GetLayoutAlgorithm(true);
2243 
2244     if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
2245         layoutAlgorithm_->SetSkipMeasure();
2246         layoutAlgorithm_->SetSkipLayout();
2247         geometryNode_->SetFrameSize(SizeF());
2248         isLayoutDirtyMarked_ = false;
2249         return;
2250     }
2251     if (!isActive_) {
2252         layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
2253     }
2254 
2255     if (layoutAlgorithm_->SkipMeasure()) {
2256         LOGD("%{public}s, depth: %{public}d: the layoutAlgorithm skip measure", GetTag().c_str(), GetDepth());
2257         isLayoutDirtyMarked_ = false;
2258         return;
2259     }
2260 
2261     const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
2262     if (geometryTransition != nullptr) {
2263         geometryTransition->WillLayout(Claim(this));
2264     }
2265     auto preConstraint = layoutProperty_->GetLayoutConstraint();
2266     auto contentConstraint = layoutProperty_->GetContentLayoutConstraint();
2267     layoutProperty_->BuildGridProperty(Claim(this));
2268 
2269     if (parentConstraint) {
2270         ApplyConstraint(*parentConstraint);
2271     } else {
2272         CreateRootConstraint();
2273     }
2274 
2275     layoutProperty_->UpdateContentConstraint();
2276     geometryNode_->UpdateMargin(layoutProperty_->CreateMargin());
2277     geometryNode_->UpdatePaddingWithBorder(layoutProperty_->CreatePaddingAndBorder());
2278 
2279     isConstraintNotChanged_ = layoutProperty_->ConstraintEqual(preConstraint, contentConstraint);
2280 
2281     LOGD("Measure: %{public}s, depth: %{public}d, Constraint: %{public}s", GetTag().c_str(), GetDepth(),
2282         layoutProperty_->GetLayoutConstraint()->ToString().c_str());
2283 
2284     isLayoutDirtyMarked_ = false;
2285 
2286     if (isConstraintNotChanged_) {
2287         if (!CheckNeedForceMeasureAndLayout()) {
2288             ACE_SCOPED_TRACE("SkipMeasure");
2289             LOGD("%{public}s (depth: %{public}d) skip measure content", GetTag().c_str(), GetDepth());
2290             layoutAlgorithm_->SetSkipMeasure();
2291             return;
2292         }
2293     }
2294 
2295     auto size = layoutAlgorithm_->MeasureContent(layoutProperty_->CreateContentConstraint(), this);
2296     if (size.has_value()) {
2297         geometryNode_->SetContentSize(size.value());
2298     }
2299     GetPercentSensitive();
2300     layoutAlgorithm_->Measure(this);
2301     if (overlayNode_) {
2302         overlayNode_->Measure(layoutProperty_->CreateChildConstraint());
2303     }
2304     UpdatePercentSensitive();
2305     // check aspect radio.
2306     if (pattern_ && pattern_->IsNeedAdjustByAspectRatio()) {
2307         const auto& magicItemProperty = layoutProperty_->GetMagicItemProperty();
2308         auto aspectRatio = magicItemProperty->GetAspectRatioValue();
2309         // Adjust by aspect ratio, firstly pick height based on width. It means that when width, height and
2310         // aspectRatio are all set, the height is not used.
2311         auto width = geometryNode_->GetFrameSize().Width();
2312         LOGD("aspect ratio affects, origin width: %{public}f, height: %{public}f", width,
2313             geometryNode_->GetFrameSize().Height());
2314         auto height = width / aspectRatio;
2315         LOGD("aspect ratio affects, new width: %{public}f, height: %{public}f", width, height);
2316         geometryNode_->SetFrameSize(SizeF({ width, height }));
2317     }
2318 
2319     LOGD("on Measure Done: type: %{public}s, depth: %{public}d, Size: %{public}s", GetTag().c_str(), GetDepth(),
2320         geometryNode_->GetFrameSize().ToString().c_str());
2321 
2322     layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
2323 }
2324 
2325 // Called to perform layout children.
Layout()2326 void FrameNode::Layout()
2327 {
2328     int64_t time = GetSysTimestamp();
2329     OffsetNodeToSafeArea();
2330     if (CheckNeedLayout(layoutProperty_->GetPropertyChangeFlag())) {
2331         if (!layoutProperty_->GetLayoutConstraint()) {
2332             const auto& parentLayoutConstraint = geometryNode_->GetParentLayoutConstraint();
2333             if (parentLayoutConstraint) {
2334                 layoutProperty_->UpdateLayoutConstraint(parentLayoutConstraint.value());
2335             } else {
2336                 LayoutConstraintF layoutConstraint;
2337                 layoutConstraint.percentReference.SetWidth(PipelineContext::GetCurrentRootWidth());
2338                 layoutConstraint.percentReference.SetHeight(PipelineContext::GetCurrentRootHeight());
2339                 layoutProperty_->UpdateLayoutConstraint(layoutConstraint);
2340             }
2341             layoutProperty_->UpdateContentConstraint();
2342         }
2343         GetLayoutAlgorithm()->Layout(this);
2344         if (overlayNode_) {
2345             LayoutOverlay();
2346         }
2347         time = GetSysTimestamp() - time;
2348         AddNodeFlexLayouts();
2349         AddNodeLayoutTime(time);
2350     } else {
2351         GetLayoutAlgorithm()->SetSkipLayout();
2352     }
2353 
2354     SaveGeoState();
2355     AvoidKeyboard();
2356     ExpandSafeArea();
2357 
2358     LOGD("On Layout Done: type: %{public}s, depth: %{public}d, Offset: %{public}s", GetTag().c_str(), GetDepth(),
2359         geometryNode_->GetFrameOffset().ToString().c_str());
2360     SyncGeometryNode();
2361 }
2362 
SyncGeometryNode()2363 void FrameNode::SyncGeometryNode()
2364 {
2365     const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
2366     bool hasTransition = geometryTransition != nullptr && geometryTransition->IsRunning();
2367 
2368     if (!isActive_ && !hasTransition) {
2369         LOGD("current node is inactive, don't need to render");
2370         layoutAlgorithm_.Reset();
2371         return;
2372     }
2373 
2374     // update layout size.
2375     bool frameSizeChange = true;
2376     bool frameOffsetChange = true;
2377     bool contentSizeChange = true;
2378     bool contentOffsetChange = true;
2379     if (oldGeometryNode_) {
2380         frameSizeChange = geometryNode_->GetFrameSize() != oldGeometryNode_->GetFrameSize();
2381         frameOffsetChange = geometryNode_->GetFrameOffset() != oldGeometryNode_->GetFrameOffset();
2382         contentSizeChange = geometryNode_->GetContentSize() != oldGeometryNode_->GetContentSize();
2383         contentOffsetChange = geometryNode_->GetContentOffset() != oldGeometryNode_->GetContentOffset();
2384         oldGeometryNode_.Reset();
2385     }
2386 
2387     // clean layout flag.
2388     layoutProperty_->CleanDirty();
2389 
2390     if (hasTransition) {
2391         geometryTransition->DidLayout(Claim(this));
2392     } else if (frameSizeChange || frameOffsetChange || HasPositionProp() ||
2393                (pattern_->GetContextParam().has_value() && contentSizeChange)) {
2394         renderContext_->SyncGeometryProperties(RawPtr(geometryNode_));
2395     }
2396 
2397     DirtySwapConfig config { frameSizeChange, frameOffsetChange, contentSizeChange, contentOffsetChange };
2398     // check if need to paint content.
2399     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(layoutAlgorithm_);
2400     CHECK_NULL_VOID(layoutAlgorithmWrapper);
2401     config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure();
2402     config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
2403     if (!config.skipMeasure && !config.skipLayout && GetInspectorId()) {
2404         auto pipeline = PipelineContext::GetCurrentContext();
2405         CHECK_NULL_VOID(pipeline);
2406         pipeline->OnLayoutCompleted(GetInspectorId()->c_str());
2407     }
2408     auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config);
2409     // TODO: temp use and need to delete.
2410     needRerender =
2411         needRerender || pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config.skipMeasure, config.skipLayout);
2412     if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
2413         MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
2414     }
2415 
2416     // update border.
2417     if (layoutProperty_->GetBorderWidthProperty()) {
2418         if (!renderContext_->HasBorderColor()) {
2419             BorderColorProperty borderColorProperty;
2420             borderColorProperty.SetColor(Color::BLACK);
2421             renderContext_->UpdateBorderColor(borderColorProperty);
2422         }
2423         if (!renderContext_->HasBorderStyle()) {
2424             BorderStyleProperty borderStyleProperty;
2425             borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
2426             renderContext_->UpdateBorderStyle(borderStyleProperty);
2427         }
2428         if (layoutProperty_->GetLayoutConstraint().has_value()) {
2429             renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
2430                 ScaleProperty::CreateScaleProperty(),
2431                 layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
2432         } else {
2433             renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
2434                 ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
2435         }
2436     }
2437 
2438     // update background
2439     if (builderFunc_) {
2440         auto builderNode = builderFunc_();
2441         auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
2442             AceType::MakeRefPtr<LinearLayoutPattern>(true));
2443         builderNode->MountToParent(columnNode);
2444         SetBackgroundLayoutConstraint(columnNode);
2445         renderContext_->CreateBackgroundPixelMap(columnNode);
2446         builderFunc_ = nullptr;
2447         backgroundNode_ = columnNode;
2448     }
2449 
2450     // update focus state
2451     auto focusHub = GetFocusHub();
2452     if (focusHub && focusHub->IsCurrentFocus()) {
2453         focusHub->ClearFocusState(false);
2454         focusHub->PaintFocusState(false);
2455     }
2456 
2457     // rebuild child render node.
2458     RebuildRenderContextTree();
2459 
2460     /* Adjust components' position which have been set grid properties */
2461     AdjustGridOffset();
2462 
2463     layoutAlgorithm_.Reset();
2464 }
2465 
GetOrCreateChildByIndex(uint32_t index,bool addToRenderTree)2466 RefPtr<LayoutWrapper> FrameNode::GetOrCreateChildByIndex(uint32_t index, bool addToRenderTree)
2467 {
2468     auto child = frameProxy_->GetFrameNodeByIndex(index, true);
2469     if (addToRenderTree && child) {
2470         child->SetActive(true);
2471     }
2472     return child;
2473 }
2474 
GetChildByIndex(uint32_t index)2475 RefPtr<LayoutWrapper> FrameNode::GetChildByIndex(uint32_t index)
2476 {
2477     return frameProxy_->GetFrameNodeByIndex(index, false);
2478 }
2479 
GetAllChildrenWithBuild(bool addToRenderTree)2480 const std::list<RefPtr<LayoutWrapper>>& FrameNode::GetAllChildrenWithBuild(bool addToRenderTree)
2481 {
2482     const auto& children = frameProxy_->GetAllFrameChildren();
2483     if (addToRenderTree) {
2484         for (const auto& child : children) {
2485             child->SetActive(true);
2486         }
2487     }
2488 
2489     return children;
2490 }
2491 
RemoveAllChildInRenderTree()2492 void FrameNode::RemoveAllChildInRenderTree()
2493 {
2494     frameProxy_->RemoveAllChildInRenderTree();
2495 }
2496 
RemoveChildInRenderTree(uint32_t index)2497 void FrameNode::RemoveChildInRenderTree(uint32_t index)
2498 {
2499     frameProxy_->RemoveChildInRenderTree(index);
2500 }
2501 
SkipMeasureContent() const2502 bool FrameNode::SkipMeasureContent() const
2503 {
2504     return layoutAlgorithm_->SkipMeasure();
2505 }
2506 
CheckNeedForceMeasureAndLayout()2507 bool FrameNode::CheckNeedForceMeasureAndLayout()
2508 {
2509     PropertyChangeFlag flag = layoutProperty_->GetPropertyChangeFlag();
2510     return CheckNeedMeasure(flag) || CheckNeedLayout(flag);
2511 }
2512 
GetBaselineDistance() const2513 float FrameNode::GetBaselineDistance() const
2514 {
2515     auto children = frameProxy_->GetAllFrameChildren();
2516     if (children.empty()) {
2517         return geometryNode_->GetBaselineDistance();
2518     }
2519     float distance = 0.0;
2520     for (const auto& child : children) {
2521         float childBaseline = child->GetBaselineDistance();
2522         distance = NearZero(distance) ? childBaseline : std::min(distance, childBaseline);
2523     }
2524     return distance;
2525 }
2526 
MarkNeedSyncRenderTree(bool needRebuild)2527 void FrameNode::MarkNeedSyncRenderTree(bool needRebuild)
2528 {
2529     if (needRebuild) {
2530         frameProxy_->ResetChildren(true);
2531     }
2532     needSyncRenderTree_ = true;
2533 }
2534 
GetFrameChildByIndex(uint32_t index,bool needBuild)2535 RefPtr<UINode> FrameNode::GetFrameChildByIndex(uint32_t index, bool needBuild)
2536 {
2537     if (index != 0) {
2538         return nullptr;
2539     }
2540     return Claim(this);
2541 }
2542 
GetLayoutAlgorithm(bool needReset)2543 const RefPtr<LayoutAlgorithmWrapper>& FrameNode::GetLayoutAlgorithm(bool needReset)
2544 {
2545     if ((!layoutAlgorithm_ || (needReset && layoutAlgorithm_->IsExpire())) && pattern_) {
2546         layoutAlgorithm_ = MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm());
2547     }
2548     if (needReset) {
2549         layoutAlgorithm_->SetNeedMeasure();
2550     }
2551     return layoutAlgorithm_;
2552 }
2553 
SetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)2554 void FrameNode::SetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
2555 {
2556     frameProxy_->SetCacheCount(cacheCount, itemConstraint);
2557 }
2558 
LayoutOverlay()2559 void FrameNode::LayoutOverlay()
2560 {
2561     auto size = geometryNode_->GetFrameSize();
2562     auto align = Alignment::TOP_LEFT;
2563     Dimension offsetX, offsetY;
2564     auto childLayoutProperty = overlayNode_->GetLayoutProperty();
2565     childLayoutProperty->GetOverlayOffset(offsetX, offsetY);
2566     auto offset = OffsetF(offsetX.ConvertToPx(), offsetY.ConvertToPx());
2567     if (childLayoutProperty->GetPositionProperty()) {
2568         align = childLayoutProperty->GetPositionProperty()->GetAlignment().value_or(align);
2569     }
2570 
2571     auto childSize = overlayNode_->GetGeometryNode()->GetMarginFrameSize();
2572     auto translate = Alignment::GetAlignPosition(size, childSize, align) + offset;
2573     overlayNode_->GetGeometryNode()->SetMarginFrameOffset(translate);
2574     overlayNode_->Layout();
2575 }
2576 
DoRemoveChildInRenderTree(uint32_t index,bool isAll)2577 void FrameNode::DoRemoveChildInRenderTree(uint32_t index, bool isAll)
2578 {
2579     isActive_ = false;
2580 }
2581 
OnInspectorIdUpdate(const std::string &)2582 void FrameNode::OnInspectorIdUpdate(const std::string& /*unused*/)
2583 {
2584     auto parent = GetAncestorNodeOfFrame();
2585     CHECK_NULL_VOID_NOLOG(parent);
2586     if (parent->GetTag() == V2::RELATIVE_CONTAINER_ETS_TAG) {
2587         parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2588     }
2589 }
2590 
2591 } // namespace OHOS::Ace::NG
2592