• 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/ng/point_t.h"
19 #include "base/log/ace_trace.h"
20 #include "base/log/dump_log.h"
21 #include "base/memory/ace_type.h"
22 #include "base/memory/referenced.h"
23 #include "base/thread/cancelable_callback.h"
24 #include "base/thread/task_executor.h"
25 #include "base/utils/system_properties.h"
26 #include "base/utils/utils.h"
27 #include "core/common/ace_application_info.h"
28 #include "core/components/common/layout/constants.h"
29 #include "core/components_ng/base/ui_node.h"
30 #include "core/components_ng/event/gesture_event_hub.h"
31 #include "core/components_ng/layout/layout_algorithm.h"
32 #include "core/components_ng/layout/layout_wrapper.h"
33 #include "core/components_ng/pattern/pattern.h"
34 #include "core/components_ng/property/measure_property.h"
35 #include "core/components_ng/property/measure_utils.h"
36 #include "core/components_ng/property/property.h"
37 #include "core/components_ng/render/paint_wrapper.h"
38 #include "core/components_v2/inspector/inspector_constants.h"
39 #include "core/pipeline_ng/pipeline_context.h"
40 #include "core/pipeline_ng/ui_task_scheduler.h"
41 
42 namespace {
43 constexpr double VISIBLE_RATIO_MIN = 0.0;
44 constexpr double VISIBLE_RATIO_MAX = 1.0;
45 } // namespace
46 namespace OHOS::Ace::NG {
FrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)47 FrameNode::FrameNode(const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
48     : UINode(tag, nodeId, isRoot), pattern_(pattern)
49 {
50     renderContext_->InitContext(IsRootNode(), pattern_->GetSurfaceNodeName(), pattern_->UseExternalRSNode());
51     paintProperty_ = pattern->CreatePaintProperty();
52     layoutProperty_ = pattern->CreateLayoutProperty();
53     eventHub_ = pattern->CreateEventHub();
54     accessibilityProperty_ = pattern->CreateAccessibilityProperty();
55     // first create make layout property dirty.
56     layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
57     layoutProperty_->SetHost(WeakClaim(this));
58 }
59 
~FrameNode()60 FrameNode::~FrameNode()
61 {
62     for (const auto& destroyCallback : destroyCallbacks_) {
63         destroyCallback();
64     }
65     pattern_->DetachFromFrameNode(this);
66     if (IsOnMainTree()) {
67         OnDetachFromMainTree();
68     }
69     auto pipeline = PipelineContext::GetCurrentContext();
70     if (pipeline) {
71         pipeline->RemoveOnAreaChangeNode(GetId());
72     }
73 }
74 
CreateFrameNodeWithTree(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern)75 RefPtr<FrameNode> FrameNode::CreateFrameNodeWithTree(
76     const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern)
77 {
78     auto newChild = CreateFrameNode(tag, nodeId, pattern, true);
79     newChild->SetDepth(1);
80     return newChild;
81 }
82 
GetOrCreateFrameNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)83 RefPtr<FrameNode> FrameNode::GetOrCreateFrameNode(
84     const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
85 {
86     auto frameNode = GetFrameNode(tag, nodeId);
87     if (frameNode) {
88         return frameNode;
89     }
90     auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
91     return CreateFrameNode(tag, nodeId, pattern);
92 }
93 
GetFrameNode(const std::string & tag,int32_t nodeId)94 RefPtr<FrameNode> FrameNode::GetFrameNode(const std::string& tag, int32_t nodeId)
95 {
96     auto frameNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(nodeId);
97     CHECK_NULL_RETURN_NOLOG(frameNode, nullptr);
98     if (frameNode->GetTag() != tag) {
99         LOGE("the tag is changed");
100         ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
101         auto parent = frameNode->GetParent();
102         if (parent) {
103             parent->RemoveChild(frameNode);
104         }
105         return nullptr;
106     }
107     return frameNode;
108 }
109 
CreateFrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)110 RefPtr<FrameNode> FrameNode::CreateFrameNode(
111     const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
112 {
113     auto frameNode = MakeRefPtr<FrameNode>(tag, nodeId, pattern, isRoot);
114     frameNode->InitializePatternAndContext();
115     ElementRegister::GetInstance()->AddUINode(frameNode);
116     return frameNode;
117 }
118 
InitializePatternAndContext()119 void FrameNode::InitializePatternAndContext()
120 {
121     eventHub_->AttachHost(WeakClaim(this));
122     pattern_->AttachToFrameNode(WeakClaim(this));
123     accessibilityProperty_->SetHost(WeakClaim(this));
124     renderContext_->SetRequestFrame([weak = WeakClaim(this)] {
125         auto frameNode = weak.Upgrade();
126         CHECK_NULL_VOID(frameNode);
127         if (frameNode->IsOnMainTree()) {
128             auto context = frameNode->GetContext();
129             CHECK_NULL_VOID(context);
130             context->RequestFrame();
131             return;
132         }
133         frameNode->hasPendingRequest_ = true;
134     });
135     renderContext_->SetHostNode(WeakClaim(this));
136     // Initialize FocusHub
137     if (pattern_->GetFocusPattern().GetFocusType() != FocusType::DISABLE) {
138         GetOrCreateFocusHub();
139     }
140 }
141 
DumpInfo()142 void FrameNode::DumpInfo()
143 {
144     DumpLog::GetInstance().AddDesc(std::string("FrameRect: ").append(geometryNode_->GetFrameRect().ToString()));
145     DumpLog::GetInstance().AddDesc(
146         std::string("BackgroundColor: ").append(renderContext_->GetBackgroundColor()->ColorToString()));
147     DumpLog::GetInstance().AddDesc(std::string("ParentLayoutConstraint: ")
148                                        .append(geometryNode_->GetParentLayoutConstraint().has_value()
149                                                    ? geometryNode_->GetParentLayoutConstraint().value().ToString()
150                                                    : "NA"));
151     DumpLog::GetInstance().AddDesc(std::string("top: ")
152                                        .append(std::to_string(GetOffsetRelativeToWindow().GetY()))
153                                        .append(" left: ")
154                                        .append(std::to_string(GetOffsetRelativeToWindow().GetX())));
155     DumpLog::GetInstance().AddDesc(std::string("Visible: ")
156                                        .append(std::to_string(static_cast<int32_t>(
157                                            layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)))));
158     if (layoutProperty_->GetPaddingProperty()) {
159         DumpLog::GetInstance().AddDesc(
160             std::string("Padding: ").append(layoutProperty_->GetPaddingProperty()->ToString().c_str()));
161     }
162     if (layoutProperty_->GetBorderWidthProperty()) {
163         DumpLog::GetInstance().AddDesc(
164             std::string("Border: ").append(layoutProperty_->GetBorderWidthProperty()->ToString().c_str()));
165     }
166     if (layoutProperty_->GetMarginProperty()) {
167         DumpLog::GetInstance().AddDesc(
168             std::string("Margin: ").append(layoutProperty_->GetMarginProperty()->ToString().c_str()));
169     }
170     DumpLog::GetInstance().AddDesc(std::string("compid: ").append(propInspectorId_.value_or("")));
171     DumpLog::GetInstance().AddDesc(std::string("ContentConstraint: ")
172                                        .append(layoutProperty_->GetContentLayoutConstraint().has_value()
173                                                    ? layoutProperty_->GetContentLayoutConstraint().value().ToString()
174                                                    : "NA"));
175     DumpLog::GetInstance().AddDesc(
176         std::string("PaintRect: ").append(renderContext_->GetPaintRectWithTransform().ToString()));
177     if (pattern_) {
178         pattern_->DumpInfo();
179     }
180     if (renderContext_) {
181         renderContext_->DumpInfo();
182     }
183 }
184 
FocusToJsonValue(std::unique_ptr<JsonValue> & json) const185 void FrameNode::FocusToJsonValue(std::unique_ptr<JsonValue>& json) const
186 {
187     bool enabled = true;
188     bool focusable = false;
189     bool focused = false;
190     bool defaultFocus = false;
191     bool groupDefaultFocus = false;
192     bool focusOnTouch = false;
193     int32_t tabIndex = 0;
194     auto focusHub = GetFocusHub();
195     if (focusHub) {
196         enabled = focusHub->IsEnabled();
197         focusable = focusHub->IsFocusable();
198         focused = focusHub->IsCurrentFocus();
199         defaultFocus = focusHub->IsDefaultFocus();
200         groupDefaultFocus = focusHub->IsDefaultGroupFocus();
201         focusOnTouch = focusHub->IsFocusOnTouch().value_or(false);
202         tabIndex = focusHub->GetTabIndex();
203     }
204     json->Put("enabled", enabled);
205     json->Put("focusable", focusable);
206     json->Put("focused", focused);
207     json->Put("defaultFocus", defaultFocus);
208     json->Put("groupDefaultFocus", groupDefaultFocus);
209     json->Put("focusOnTouch", focusOnTouch);
210     json->Put("tabIndex", tabIndex);
211 }
212 
MouseToJsonValue(std::unique_ptr<JsonValue> & json) const213 void FrameNode::MouseToJsonValue(std::unique_ptr<JsonValue>& json) const
214 {
215     std::string hoverEffect = "HoverEffect.Auto";
216     auto inputEventHub = GetOrCreateInputEventHub();
217     if (inputEventHub) {
218         hoverEffect = inputEventHub->GetHoverEffectStr();
219     }
220     json->Put("hoverEffect", hoverEffect.c_str());
221 }
222 
TouchToJsonValue(std::unique_ptr<JsonValue> & json) const223 void FrameNode::TouchToJsonValue(std::unique_ptr<JsonValue>& json) const
224 {
225     bool touchable = true;
226     std::string hitTestMode = "HitTestMode.Default";
227     auto gestureEventHub = GetOrCreateGestureEventHub();
228     std::vector<DimensionRect> responseRegion;
229     if (gestureEventHub) {
230         touchable = gestureEventHub->GetTouchable();
231         hitTestMode = gestureEventHub->GetHitTestModeStr();
232         responseRegion = gestureEventHub->GetResponseRegion();
233     }
234     json->Put("touchable", touchable);
235     json->Put("hitTestBehavior", hitTestMode.c_str());
236     auto jsArr = JsonUtil::CreateArray(true);
237     for (int32_t i = 0; i < static_cast<int32_t>(responseRegion.size()); ++i) {
238         auto iStr = std::to_string(i);
239         jsArr->Put(iStr.c_str(), responseRegion[i].ToJsonString().c_str());
240     }
241     json->Put("responseRegion", jsArr);
242 }
243 
ToJsonValue(std::unique_ptr<JsonValue> & json) const244 void FrameNode::ToJsonValue(std::unique_ptr<JsonValue>& json) const
245 {
246     if (renderContext_) {
247         renderContext_->ToJsonValue(json);
248     }
249     // scrollable in AccessibilityProperty
250     ACE_PROPERTY_TO_JSON_VALUE(accessibilityProperty_, AccessibilityProperty);
251     ACE_PROPERTY_TO_JSON_VALUE(layoutProperty_, LayoutProperty);
252     ACE_PROPERTY_TO_JSON_VALUE(paintProperty_, PaintProperty);
253     ACE_PROPERTY_TO_JSON_VALUE(pattern_, Pattern);
254     if (eventHub_) {
255         eventHub_->ToJsonValue(json);
256     }
257     FocusToJsonValue(json);
258     MouseToJsonValue(json);
259     TouchToJsonValue(json);
260     json->Put("id", propInspectorId_.value_or("").c_str());
261 }
262 
OnAttachToMainTree()263 void FrameNode::OnAttachToMainTree()
264 {
265     UINode::OnAttachToMainTree();
266     eventHub_->FireOnAppear();
267     renderContext_->OnNodeAppear();
268     if (IsResponseRegion() || HasPositionProp()) {
269         auto parent = GetParent();
270         while (parent) {
271             auto frameNode = AceType::DynamicCast<FrameNode>(parent);
272             if (frameNode) {
273                 frameNode->MarkResponseRegion(true);
274             }
275             parent = parent->GetParent();
276         }
277     }
278     if (!hasPendingRequest_) {
279         return;
280     }
281     auto context = GetContext();
282     CHECK_NULL_VOID(context);
283     context->RequestFrame();
284     hasPendingRequest_ = false;
285 }
286 
OnVisibleChange(bool isVisible)287 void FrameNode::OnVisibleChange(bool isVisible)
288 {
289     pattern_->OnVisibleChange(isVisible);
290     for (const auto& child : GetChildren()) {
291         child->OnVisibleChange(isVisible);
292     }
293 }
294 
OnDetachFromMainTree()295 void FrameNode::OnDetachFromMainTree()
296 {
297     eventHub_->FireOnDisappear();
298     renderContext_->OnNodeDisappear();
299 }
300 
SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper> & dirty)301 void FrameNode::SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper>& dirty)
302 {
303     ACE_FUNCTION_TRACE();
304     LOGD("SwapDirtyLayoutWrapperOnMainThread, %{public}s", GetTag().c_str());
305     CHECK_NULL_VOID(dirty);
306 
307     // update new layout constrain.
308     layoutProperty_->UpdateLayoutConstraint(dirty->GetLayoutProperty());
309 
310     // active change flag judge.
311     SetActive(dirty->IsActive());
312     if (!isActive_) {
313         LOGD("current node is inactive, don't need to render");
314         return;
315     }
316 
317     // update layout size.
318     bool frameSizeChange = geometryNode_->GetFrameSize() != dirty->GetGeometryNode()->GetFrameSize();
319     bool frameOffsetChange = geometryNode_->GetFrameOffset() != dirty->GetGeometryNode()->GetFrameOffset();
320     bool contentSizeChange = geometryNode_->GetContentSize() != dirty->GetGeometryNode()->GetContentSize();
321     bool contentOffsetChange = geometryNode_->GetContentOffset() != dirty->GetGeometryNode()->GetContentOffset();
322 
323     SetGeometryNode(dirty->GetGeometryNode());
324     if (frameSizeChange || frameOffsetChange || HasPositionProp() ||
325         (pattern_->GetSurfaceNodeName().has_value() && contentSizeChange)) {
326         if (pattern_->NeedOverridePaintRect()) {
327             renderContext_->SyncGeometryProperties(pattern_->GetOverridePaintRect().value_or(RectF()));
328         } else {
329             renderContext_->SyncGeometryProperties(RawPtr(dirty->GetGeometryNode()));
330         }
331     }
332 
333     // clean layout flag.
334     layoutProperty_->CleanDirty();
335     DirtySwapConfig config { frameSizeChange, frameOffsetChange, contentSizeChange, contentOffsetChange };
336     // check if need to paint content.
337     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
338     CHECK_NULL_VOID(layoutAlgorithmWrapper);
339     config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure() || dirty->SkipMeasureContent();
340     config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
341     auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(dirty, config);
342     // TODO: temp use and need to delete.
343     needRerender = needRerender || pattern_->OnDirtyLayoutWrapperSwap(dirty, config.skipMeasure, config.skipLayout);
344     if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
345         MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
346     }
347 
348     // update border.
349     if (layoutProperty_->GetBorderWidthProperty()) {
350         if (!renderContext_->HasBorderColor()) {
351             BorderColorProperty borderColorProperty;
352             borderColorProperty.SetColor(Color::BLACK);
353             renderContext_->UpdateBorderColor(borderColorProperty);
354         }
355         if (!renderContext_->HasBorderStyle()) {
356             BorderStyleProperty borderStyleProperty;
357             borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
358             renderContext_->UpdateBorderStyle(borderStyleProperty);
359         }
360         if (layoutProperty_->GetLayoutConstraint().has_value()) {
361             renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
362                 ScaleProperty::CreateScaleProperty(),
363                 layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
364         } else {
365             renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
366                 ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
367         }
368     }
369 
370     // update focus state
371     auto focusHub = GetFocusHub();
372     if (focusHub && focusHub->IsCurrentFocus()) {
373         focusHub->ClearFocusState();
374         focusHub->PaintFocusState();
375     }
376 
377     // rebuild child render node.
378     RebuildRenderContextTree();
379 }
380 
AdjustGridOffset()381 void FrameNode::AdjustGridOffset()
382 {
383     if (!isActive_) {
384         return;
385     }
386     if (layoutProperty_->UpdateGridOffset(Claim(this))) {
387         renderContext_->UpdateOffset(OffsetT<Dimension>());
388         renderContext_->UpdateAnchor(OffsetT<Dimension>());
389         renderContext_->SyncGeometryProperties(RawPtr(GetGeometryNode()));
390     }
391 }
392 
SetOnAreaChangeCallback(OnAreaChangedFunc && callback)393 void FrameNode::SetOnAreaChangeCallback(OnAreaChangedFunc&& callback)
394 {
395     if (!lastFrameRect_) {
396         lastFrameRect_ = std::make_unique<RectF>();
397     }
398     if (!lastParentOffsetToWindow_) {
399         lastParentOffsetToWindow_ = std::make_unique<OffsetF>();
400     }
401     eventHub_->SetOnAreaChanged(std::move(callback));
402 }
403 
TriggerOnAreaChangeCallback()404 void FrameNode::TriggerOnAreaChangeCallback()
405 {
406     if (eventHub_->HasOnAreaChanged() && lastFrameRect_ && lastParentOffsetToWindow_) {
407         auto currFrameRect = geometryNode_->GetFrameRect();
408         auto currParentOffsetToWindow = GetOffsetRelativeToWindow() - currFrameRect.GetOffset();
409         if (currFrameRect != *lastFrameRect_ || currParentOffsetToWindow != *lastParentOffsetToWindow_) {
410             eventHub_->FireOnAreaChanged(
411                 *lastFrameRect_, *lastParentOffsetToWindow_, currFrameRect, currParentOffsetToWindow);
412             *lastFrameRect_ = currFrameRect;
413             *lastParentOffsetToWindow_ = currParentOffsetToWindow;
414         }
415     }
416     pattern_->OnAreaChangedInner();
417 }
418 
TriggerVisibleAreaChangeCallback(std::list<VisibleCallbackInfo> & callbackInfoList)419 void FrameNode::TriggerVisibleAreaChangeCallback(std::list<VisibleCallbackInfo>& callbackInfoList)
420 {
421     auto context = PipelineContext::GetCurrentContext();
422     CHECK_NULL_VOID(context);
423 
424     bool curFrameIsActive = true;
425     auto parent = GetParent();
426     while (parent) {
427         auto parentFrame = AceType::DynamicCast<FrameNode>(parent);
428         if (!parentFrame) {
429             parent = parent->GetParent();
430             continue;
431         }
432         if (!parentFrame->isActive_) {
433             curFrameIsActive = false;
434             break;
435         }
436         parent = parent->GetParent();
437     }
438 
439     if (!context->GetOnShow() || !IsVisible() || !curFrameIsActive) {
440         if (!NearEqual(lastVisibleRatio_, VISIBLE_RATIO_MIN)) {
441             ProcessAllVisibleCallback(callbackInfoList, VISIBLE_RATIO_MIN);
442             lastVisibleRatio_ = VISIBLE_RATIO_MIN;
443         }
444         return;
445     }
446 
447     auto frameRect = renderContext_->GetPaintRectWithTransform();
448     frameRect.SetOffset(GetOffsetRelativeToWindow());
449     auto visibleRect = frameRect;
450     RectF parentRect;
451     auto parentUi = GetParent();
452     while (parentUi) {
453         auto parentFrame = AceType::DynamicCast<FrameNode>(parentUi);
454         if (!parentFrame) {
455             parentUi = parentUi->GetParent();
456             continue;
457         }
458         parentRect = parentFrame->GetRenderContext()->GetPaintRectWithTransform();
459         parentRect.SetOffset(parentFrame->GetOffsetRelativeToWindow());
460         visibleRect = visibleRect.Constrain(parentRect);
461         parentUi = parentUi->GetParent();
462     }
463 
464     double currentVisibleRatio =
465         std::clamp(CalculateCurrentVisibleRatio(visibleRect, frameRect), VISIBLE_RATIO_MIN, VISIBLE_RATIO_MAX);
466     if (!NearEqual(currentVisibleRatio, lastVisibleRatio_)) {
467         ProcessAllVisibleCallback(callbackInfoList, currentVisibleRatio);
468         lastVisibleRatio_ = currentVisibleRatio;
469     }
470 }
471 
CalculateCurrentVisibleRatio(const RectF & visibleRect,const RectF & renderRect)472 double FrameNode::CalculateCurrentVisibleRatio(const RectF& visibleRect, const RectF& renderRect)
473 {
474     if (!visibleRect.IsValid() || !renderRect.IsValid()) {
475         return 0.0;
476     }
477     return visibleRect.Width() * visibleRect.Height() / (renderRect.Width() * renderRect.Height());
478 }
479 
ProcessAllVisibleCallback(std::list<VisibleCallbackInfo> & callbackInfoList,double currentVisibleRatio)480 void FrameNode::ProcessAllVisibleCallback(std::list<VisibleCallbackInfo>& callbackInfoList, double currentVisibleRatio)
481 {
482     for (auto& nodeCallbackInfo : callbackInfoList) {
483         if (GreatNotEqual(currentVisibleRatio, nodeCallbackInfo.visibleRatio) && !nodeCallbackInfo.isCurrentVisible) {
484             OnVisibleAreaChangeCallback(nodeCallbackInfo, true, currentVisibleRatio);
485             continue;
486         }
487 
488         if (LessNotEqual(currentVisibleRatio, nodeCallbackInfo.visibleRatio) && nodeCallbackInfo.isCurrentVisible) {
489             OnVisibleAreaChangeCallback(nodeCallbackInfo, false, currentVisibleRatio);
490             continue;
491         }
492 
493         if (NearEqual(currentVisibleRatio, nodeCallbackInfo.visibleRatio) &&
494             NearEqual(nodeCallbackInfo.visibleRatio, VISIBLE_RATIO_MIN)) {
495             if (nodeCallbackInfo.isCurrentVisible) {
496                 OnVisibleAreaChangeCallback(nodeCallbackInfo, false, VISIBLE_RATIO_MIN);
497             } else {
498                 OnVisibleAreaChangeCallback(nodeCallbackInfo, true, VISIBLE_RATIO_MIN);
499             }
500         } else if (NearEqual(currentVisibleRatio, nodeCallbackInfo.visibleRatio) &&
501                    NearEqual(nodeCallbackInfo.visibleRatio, VISIBLE_RATIO_MAX)) {
502             if (!nodeCallbackInfo.isCurrentVisible) {
503                 OnVisibleAreaChangeCallback(nodeCallbackInfo, true, VISIBLE_RATIO_MAX);
504             } else {
505                 OnVisibleAreaChangeCallback(nodeCallbackInfo, false, VISIBLE_RATIO_MAX);
506             }
507         }
508     }
509 }
510 
OnVisibleAreaChangeCallback(VisibleCallbackInfo & callbackInfo,bool visibleType,double currentVisibleRatio)511 void FrameNode::OnVisibleAreaChangeCallback(
512     VisibleCallbackInfo& callbackInfo, bool visibleType, double currentVisibleRatio)
513 {
514     callbackInfo.isCurrentVisible = visibleType;
515     if (callbackInfo.callback) {
516         callbackInfo.callback(visibleType, currentVisibleRatio);
517     }
518 }
519 
SetActive(bool active)520 void FrameNode::SetActive(bool active)
521 {
522     bool activeChanged = false;
523     if (active && !isActive_) {
524         pattern_->OnActive();
525         isActive_ = true;
526         activeChanged = true;
527     }
528     if (!active && isActive_) {
529         pattern_->OnInActive();
530         isActive_ = false;
531         activeChanged = true;
532     }
533     if (activeChanged) {
534         auto parent = GetAncestorNodeOfFrame();
535         if (parent) {
536             parent->MarkNeedSyncRenderTree();
537         }
538     }
539 }
540 
SetGeometryNode(const RefPtr<GeometryNode> & node)541 void FrameNode::SetGeometryNode(const RefPtr<GeometryNode>& node)
542 {
543     geometryNode_ = node;
544 }
545 
CreateLayoutTask(bool forceUseMainThread)546 std::optional<UITask> FrameNode::CreateLayoutTask(bool forceUseMainThread)
547 {
548     if (!isLayoutDirtyMarked_) {
549         return std::nullopt;
550     }
551     ACE_SCOPED_TRACE("CreateLayoutTask:PrepareTask");
552     RefPtr<LayoutWrapper> layoutWrapper;
553     UpdateLayoutPropertyFlag();
554     layoutWrapper = CreateLayoutWrapper();
555     CHECK_NULL_RETURN_NOLOG(layoutWrapper, std::nullopt);
556     auto task = [layoutWrapper, layoutConstraint = GetLayoutConstraint(), forceUseMainThread]() {
557         layoutWrapper->SetActive();
558         layoutWrapper->SetRootMeasureNode();
559         {
560             ACE_SCOPED_TRACE("LayoutWrapper::Measure");
561             layoutWrapper->Measure(layoutConstraint);
562         }
563         {
564             ACE_SCOPED_TRACE("LayoutWrapper::Layout");
565             layoutWrapper->Layout();
566         }
567         {
568             ACE_SCOPED_TRACE("LayoutWrapper::MountToHostOnMainThread");
569             if (forceUseMainThread || layoutWrapper->CheckShouldRunOnMain()) {
570                 layoutWrapper->MountToHostOnMainThread();
571                 return;
572             }
573             auto host = layoutWrapper->GetHostNode();
574             CHECK_NULL_VOID(host);
575             host->PostTask([layoutWrapper]() { layoutWrapper->MountToHostOnMainThread(); });
576         }
577     };
578     if (forceUseMainThread || layoutWrapper->CheckShouldRunOnMain()) {
579         return UITask(std::move(task), MAIN_TASK);
580     }
581     return UITask(std::move(task), layoutWrapper->CanRunOnWhichThread());
582 }
583 
CreateRenderTask(bool forceUseMainThread)584 std::optional<UITask> FrameNode::CreateRenderTask(bool forceUseMainThread)
585 {
586     if (!isRenderDirtyMarked_) {
587         return std::nullopt;
588     }
589     ACE_SCOPED_TRACE("CreateRenderTask:PrepareTask");
590     auto wrapper = CreatePaintWrapper();
591     CHECK_NULL_RETURN_NOLOG(wrapper, std::nullopt);
592     auto task = [wrapper, paintProperty = paintProperty_]() {
593         ACE_SCOPED_TRACE("FrameNode::RenderTask");
594         wrapper->FlushRender();
595         paintProperty->CleanDirty();
596     };
597     if (forceUseMainThread || wrapper->CheckShouldRunOnMain()) {
598         return UITask(std::move(task), MAIN_TASK);
599     }
600     return UITask(std::move(task), wrapper->CanRunOnWhichThread());
601 }
602 
GetLayoutConstraint() const603 LayoutConstraintF FrameNode::GetLayoutConstraint() const
604 {
605     if (geometryNode_->GetParentLayoutConstraint().has_value()) {
606         return geometryNode_->GetParentLayoutConstraint().value();
607     }
608     LayoutConstraintF layoutConstraint;
609     layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
610     auto rootWidth = PipelineContext::GetCurrentRootWidth();
611     auto rootHeight = PipelineContext::GetCurrentRootHeight();
612     layoutConstraint.percentReference.SetWidth(rootWidth);
613     layoutConstraint.percentReference.SetHeight(rootHeight);
614     layoutConstraint.maxSize.SetWidth(rootWidth);
615     layoutConstraint.maxSize.SetHeight(rootHeight);
616     return layoutConstraint;
617 }
618 
GetParentGlobalOffset() const619 OffsetF FrameNode::GetParentGlobalOffset() const
620 {
621     auto parent = GetAncestorNodeOfFrame();
622     if (!parent) {
623         return { 0.0f, 0.0f };
624     }
625     return parent->geometryNode_->GetParentGlobalOffset();
626 }
627 
UpdateLayoutPropertyFlag()628 void FrameNode::UpdateLayoutPropertyFlag()
629 {
630     auto selfFlag = layoutProperty_->GetPropertyChangeFlag();
631     if (!CheckUpdateByChildRequest(selfFlag)) {
632         return;
633     }
634     if (CheckForceParentMeasureFlag(selfFlag)) {
635         return;
636     }
637     auto flag = PROPERTY_UPDATE_NORMAL;
638     const auto& children = GetChildren();
639     for (const auto& child : children) {
640         child->UpdateLayoutPropertyFlag();
641         child->AdjustParentLayoutFlag(flag);
642         if (CheckForceParentMeasureFlag(selfFlag)) {
643             break;
644         }
645     }
646     if (CheckForceParentMeasureFlag(flag)) {
647         layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
648     }
649 }
650 
AdjustParentLayoutFlag(PropertyChangeFlag & flag)651 void FrameNode::AdjustParentLayoutFlag(PropertyChangeFlag& flag)
652 {
653     flag = flag | layoutProperty_->GetPropertyChangeFlag();
654 }
655 
CreateLayoutWrapper(bool forceMeasure,bool forceLayout)656 RefPtr<LayoutWrapper> FrameNode::CreateLayoutWrapper(bool forceMeasure, bool forceLayout)
657 {
658     CHECK_NULL_RETURN_NOLOG(layoutProperty_, nullptr);
659     CHECK_NULL_RETURN_NOLOG(pattern_, nullptr);
660     if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
661         auto layoutWrapper =
662             MakeRefPtr<LayoutWrapper>(WeakClaim(this), MakeRefPtr<GeometryNode>(), MakeRefPtr<LayoutProperty>());
663         layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
664         isLayoutDirtyMarked_ = false;
665         return layoutWrapper;
666     }
667 
668     pattern_->BeforeCreateLayoutWrapper();
669     if (!isActive_ || forceMeasure) {
670         layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
671     }
672     if (forceLayout) {
673         layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
674     }
675     auto flag = layoutProperty_->GetPropertyChangeFlag();
676     // It is necessary to copy the layoutProperty property to prevent the layoutProperty property from being modified
677     // during the layout process, resulting in the problem of judging whether the front-end setting value changes the
678     // next time js is executed.
679     auto layoutWrapper = MakeRefPtr<LayoutWrapper>(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
680     LOGD("%{public}s create layout wrapper: %{public}x, %{public}d, %{public}d", GetTag().c_str(), flag, forceMeasure,
681         forceLayout);
682     do {
683         if (CheckNeedMeasure(flag) || forceMeasure) {
684             layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm()));
685             bool forceChildMeasure = CheckMeasureFlag(flag) || forceMeasure;
686             UpdateChildrenLayoutWrapper(layoutWrapper, forceChildMeasure, false);
687             break;
688         }
689         if (CheckNeedLayout(flag) || forceLayout) {
690             layoutWrapper->SetLayoutAlgorithm(
691                 MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm(), true, false));
692             UpdateChildrenLayoutWrapper(layoutWrapper, false, false);
693             break;
694         }
695         layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
696     } while (false);
697     // check position flag.
698     layoutWrapper->SetOutOfLayout(renderContext_->HasPosition());
699     layoutWrapper->SetActive(isActive_);
700     isLayoutDirtyMarked_ = false;
701     return layoutWrapper;
702 }
703 
UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapper> & self,bool forceMeasure,bool forceLayout)704 void FrameNode::UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapper>& self, bool forceMeasure, bool forceLayout)
705 {
706     const auto& children = GetChildren();
707     for (const auto& child : children) {
708         child->AdjustLayoutWrapperTree(self, forceMeasure, forceLayout);
709     }
710 }
711 
AdjustLayoutWrapperTree(const RefPtr<LayoutWrapper> & parent,bool forceMeasure,bool forceLayout)712 void FrameNode::AdjustLayoutWrapperTree(const RefPtr<LayoutWrapper>& parent, bool forceMeasure, bool forceLayout)
713 {
714     ACE_DCHECK(parent);
715     auto layoutWrapper = CreateLayoutWrapper(forceMeasure, forceLayout);
716     parent->AppendChild(layoutWrapper);
717 }
718 
CreatePaintWrapper()719 RefPtr<PaintWrapper> FrameNode::CreatePaintWrapper()
720 {
721     pattern_->BeforeCreatePaintWrapper();
722     isRenderDirtyMarked_ = false;
723     auto paintMethod = pattern_->CreateNodePaintMethod();
724     // It is necessary to copy the layoutProperty property to prevent the paintProperty_ property from being modified
725     // during the paint process, resulting in the problem of judging whether the front-end setting value changes the
726     // next time js is executed.
727     if (paintMethod) {
728         auto paintWrapper = MakeRefPtr<PaintWrapper>(renderContext_, geometryNode_->Clone(), paintProperty_->Clone());
729         paintWrapper->SetNodePaintMethod(paintMethod);
730         return paintWrapper;
731     }
732     if (renderContext_->GetAccessibilityFocus().value_or(false)) {
733         auto paintWrapper = MakeRefPtr<PaintWrapper>(renderContext_, geometryNode_->Clone(), paintProperty_->Clone());
734         paintWrapper->SetNodePaintMethod(MakeRefPtr<NodePaintMethod>());
735         return paintWrapper;
736     }
737     return nullptr;
738 }
739 
PostTask(std::function<void ()> && task,TaskExecutor::TaskType taskType)740 void FrameNode::PostTask(std::function<void()>&& task, TaskExecutor::TaskType taskType)
741 {
742     auto context = GetContext();
743     CHECK_NULL_VOID(context);
744     context->PostAsyncEvent(std::move(task), taskType);
745 }
746 
UpdateLayoutConstraint(const MeasureProperty & calcLayoutConstraint)747 void FrameNode::UpdateLayoutConstraint(const MeasureProperty& calcLayoutConstraint)
748 {
749     layoutProperty_->UpdateCalcLayoutProperty(calcLayoutConstraint);
750 }
751 
RebuildRenderContextTree()752 void FrameNode::RebuildRenderContextTree()
753 {
754     if (!needSyncRenderTree_) {
755         return;
756     }
757     frameChildren_.clear();
758     std::list<RefPtr<FrameNode>> children;
759     GenerateOneDepthVisibleFrame(children);
760     frameChildren_ = { children.begin(), children.end() };
761     renderContext_->RebuildFrame(this, children);
762     pattern_->OnRebuildFrame();
763     needSyncRenderTree_ = false;
764 }
765 
MarkModifyDone()766 void FrameNode::MarkModifyDone()
767 {
768     pattern_->OnModifyDone();
769     eventHub_->MarkModifyDone();
770     if (IsResponseRegion() || HasPositionProp()) {
771         auto parent = GetParent();
772         while (parent) {
773             auto frameNode = AceType::DynamicCast<FrameNode>(parent);
774             if (frameNode) {
775                 frameNode->MarkResponseRegion(true);
776             }
777             parent = parent->GetParent();
778         }
779     }
780     renderContext_->OnModifyDone();
781 }
782 
OnMountToParentDone()783 void FrameNode::OnMountToParentDone()
784 {
785     pattern_->OnMountToParentDone();
786 }
787 
FlushUpdateAndMarkDirty()788 void FrameNode::FlushUpdateAndMarkDirty()
789 {
790     MarkDirtyNode();
791 }
792 
MarkDirtyNode(PropertyChangeFlag extraFlag)793 void FrameNode::MarkDirtyNode(PropertyChangeFlag extraFlag)
794 {
795     MarkDirtyNode(IsMeasureBoundary(), IsRenderBoundary(), extraFlag);
796 }
797 
GetAncestorNodeOfFrame() const798 RefPtr<FrameNode> FrameNode::GetAncestorNodeOfFrame() const
799 {
800     auto parent = GetParent();
801     while (parent) {
802         if (InstanceOf<FrameNode>(parent)) {
803             return DynamicCast<FrameNode>(parent);
804         }
805         parent = parent->GetParent();
806     }
807     return nullptr;
808 }
809 
MarkNeedRenderOnly()810 void FrameNode::MarkNeedRenderOnly()
811 {
812     MarkNeedRender(IsRenderBoundary());
813 }
814 
MarkNeedRender(bool isRenderBoundary)815 void FrameNode::MarkNeedRender(bool isRenderBoundary)
816 {
817     auto context = GetContext();
818     CHECK_NULL_VOID(context);
819     // If it has dirtyLayoutBox, need to mark dirty after layout done.
820     paintProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_RENDER);
821     if (isRenderDirtyMarked_ || isLayoutDirtyMarked_) {
822         LOGD("this node has already mark dirty, %{public}s, %{public}d, %{public}d", GetTag().c_str(),
823             isRenderDirtyMarked_, isLayoutDirtyMarked_);
824         return;
825     }
826     isRenderDirtyMarked_ = true;
827     if (isRenderBoundary) {
828         context->AddDirtyRenderNode(Claim(this));
829         return;
830     }
831     auto parent = GetAncestorNodeOfFrame();
832     if (parent) {
833         parent->MarkDirtyNode(PROPERTY_UPDATE_RENDER_BY_CHILD_REQUEST);
834     }
835 }
836 
MarkDirtyNode(bool isMeasureBoundary,bool isRenderBoundary,PropertyChangeFlag extraFlag)837 void FrameNode::MarkDirtyNode(bool isMeasureBoundary, bool isRenderBoundary, PropertyChangeFlag extraFlag)
838 {
839     if (CheckNeedRender(extraFlag)) {
840         paintProperty_->UpdatePropertyChangeFlag(extraFlag);
841     }
842     layoutProperty_->UpdatePropertyChangeFlag(extraFlag);
843     paintProperty_->UpdatePropertyChangeFlag(extraFlag);
844     auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
845     auto paintFlag = paintProperty_->GetPropertyChangeFlag();
846     if (CheckNoChanged(layoutFlag | paintFlag)) {
847         LOGD("MarkDirtyNode: flag not changed, node tag: %{public}s", GetTag().c_str());
848         return;
849     }
850     auto context = GetContext();
851     CHECK_NULL_VOID(context);
852 
853     if (CheckNeedRequestMeasureAndLayout(layoutFlag)) {
854         if (!isMeasureBoundary && IsNeedRequestParentMeasure()) {
855             auto parent = GetAncestorNodeOfFrame();
856             if (parent) {
857                 parent->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
858                 return;
859             }
860         }
861         if (isLayoutDirtyMarked_) {
862             LOGD("MarkDirtyNode: isLayoutDirtyMarked is true");
863             return;
864         }
865         isLayoutDirtyMarked_ = true;
866         context->AddDirtyLayoutNode(Claim(this));
867         return;
868     }
869     layoutProperty_->CleanDirty();
870     MarkNeedRender(isRenderBoundary);
871 }
872 
IsNeedRequestParentMeasure() const873 bool FrameNode::IsNeedRequestParentMeasure() const
874 {
875     auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
876     if (layoutFlag == PROPERTY_UPDATE_BY_CHILD_REQUEST) {
877         const auto& calcLayoutConstraint = layoutProperty_->GetCalcLayoutConstraint();
878         if (calcLayoutConstraint && calcLayoutConstraint->selfIdealSize &&
879             calcLayoutConstraint->selfIdealSize->IsValid()) {
880             LOGD("make self measure boundary");
881             return false;
882         }
883     }
884     return CheckNeedRequestParentMeasure(layoutFlag);
885 }
886 
OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & visibleList)887 void FrameNode::OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& visibleList)
888 {
889     if (isActive_ && IsVisible()) {
890         visibleList.emplace_back(Claim(this));
891     }
892 }
893 
OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>> & allList)894 void FrameNode::OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>>& allList)
895 {
896     allList.emplace_back(Claim(this));
897 }
898 
IsMeasureBoundary()899 bool FrameNode::IsMeasureBoundary()
900 {
901     return isMeasureBoundary_ || pattern_->IsMeasureBoundary();
902 }
903 
IsRenderBoundary()904 bool FrameNode::IsRenderBoundary()
905 {
906     return pattern_->IsRenderBoundary();
907 }
908 
GetPattern() const909 const RefPtr<Pattern>& FrameNode::GetPattern() const
910 {
911     return pattern_;
912 }
913 
IsAtomicNode() const914 bool FrameNode::IsAtomicNode() const
915 {
916     return pattern_->IsAtomicNode();
917 }
918 
GetHitTestMode() const919 HitTestMode FrameNode::GetHitTestMode() const
920 {
921     auto gestureHub = eventHub_->GetGestureEventHub();
922     return gestureHub ? gestureHub->GetHitTestMode() : HitTestMode::HTMDEFAULT;
923 }
924 
GetTouchable() const925 bool FrameNode::GetTouchable() const
926 {
927     auto gestureHub = eventHub_->GetGestureEventHub();
928     return gestureHub ? gestureHub->GetTouchable() : true;
929 }
930 
IsResponseRegion() const931 bool FrameNode::IsResponseRegion() const
932 {
933     if (!pattern_->UsResRegion()) {
934         return false;
935     }
936     auto gestureHub = eventHub_->GetGestureEventHub();
937     return gestureHub ? gestureHub->IsResponseRegion() : false;
938 }
939 
MarkResponseRegion(bool isResponseRegion)940 void FrameNode::MarkResponseRegion(bool isResponseRegion)
941 {
942     auto gestureHub = eventHub_->GetOrCreateGestureEventHub();
943     if (gestureHub) {
944         gestureHub->MarkResponseRegion(isResponseRegion);
945     }
946 }
947 
IsOutOfTouchTestRegion(const PointF & parentLocalPoint)948 bool FrameNode::IsOutOfTouchTestRegion(const PointF& parentLocalPoint)
949 {
950     bool isInChildRegion = false;
951     auto paintRect = renderContext_->GetPaintRectWithTransform();
952     auto responseRegionList = GetResponseRegionList(paintRect);
953     auto localPoint = parentLocalPoint - paintRect.GetOffset();
954     if (!InResponseRegionList(parentLocalPoint, responseRegionList) || !GetTouchable()) {
955         if (!pattern_->UsResRegion()) {
956             LOGD("TouchTest: not use resRegion, point is out of region in %{public}s", GetTag().c_str());
957             return true;
958         }
959         for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
960             const auto& child = *iter;
961             if (!child->IsOutOfTouchTestRegion(localPoint)) {
962                 LOGD("TouchTest: point is out of region in %{public}s, but is in child region", GetTag().c_str());
963                 isInChildRegion = true;
964                 break;
965             }
966         }
967         if (!isInChildRegion) {
968             LOGD("TouchTest: point is out of region in %{public}s", GetTag().c_str());
969             return true;
970         }
971     }
972     return false;
973 }
974 
TouchTest(const PointF & globalPoint,const PointF & parentLocalPoint,const TouchRestrict & touchRestrict,TouchTestResult & result,int32_t touchId)975 HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& parentLocalPoint,
976     const TouchRestrict& touchRestrict, TouchTestResult& result, int32_t touchId)
977 {
978     if (!isActive_ || !eventHub_->IsEnabled()) {
979         LOGE("%{public}s is inActive, need't do touch test", GetTag().c_str());
980         return HitTestResult::OUT_OF_REGION;
981     }
982     auto paintRect = renderContext_->GetPaintRectWithTransform();
983     auto responseRegionList = GetResponseRegionList(paintRect);
984     if (SystemProperties::GetDebugEnabled()) {
985         LOGD("TouchTest: point is %{public}s in %{public}s, depth: %{public}d", parentLocalPoint.ToString().c_str(),
986             GetTag().c_str(), GetDepth());
987         for (const auto& rect : responseRegionList) {
988             LOGD("TouchTest: responseRegionList is %{public}s, point is %{public}s", rect.ToString().c_str(),
989                 parentLocalPoint.ToString().c_str());
990         }
991     }
992 
993     if (IsOutOfTouchTestRegion(parentLocalPoint)) {
994         return HitTestResult::OUT_OF_REGION;
995     }
996 
997     HitTestResult testResult = HitTestResult::OUT_OF_REGION;
998     bool preventBubbling = false;
999     // Child nodes are repackaged into gesture groups (parallel gesture groups, exclusive gesture groups, etc.) based on
1000     // the gesture attributes set by the current parent node (high and low priority, parallel gestures, etc.), the
1001     // newComingTargets is the template object to collect child nodes gesture and used by gestureHub to pack gesture
1002     // group.
1003     TouchTestResult newComingTargets;
1004     auto tmp = parentLocalPoint - paintRect.GetOffset();
1005     renderContext_->GetPointWithTransform(tmp);
1006     const auto localPoint = tmp;
1007     bool consumed = false;
1008     for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
1009         if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
1010             break;
1011         }
1012 
1013         const auto& child = *iter;
1014         auto childHitResult = child->TouchTest(globalPoint, localPoint, touchRestrict, newComingTargets, touchId);
1015         if (childHitResult == HitTestResult::STOP_BUBBLING) {
1016             preventBubbling = true;
1017             consumed = true;
1018             if ((child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
1019                 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF)) {
1020                 break;
1021             }
1022         }
1023 
1024         // In normal process, the node block the brother node.
1025         if (childHitResult == HitTestResult::BUBBLING &&
1026             ((child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
1027                 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF))) {
1028             consumed = true;
1029             break;
1030         }
1031     }
1032 
1033     // first update HitTestResult by children status.
1034     if (consumed) {
1035         testResult = preventBubbling ? HitTestResult::STOP_BUBBLING : HitTestResult::BUBBLING;
1036         consumed = false;
1037     }
1038 
1039     if (!preventBubbling && (GetHitTestMode() != HitTestMode::HTMNONE) &&
1040         InResponseRegionList(parentLocalPoint, responseRegionList)) {
1041         consumed = true;
1042         if (touchRestrict.hitTestType == SourceType::TOUCH) {
1043             auto gestureHub = eventHub_->GetGestureEventHub();
1044             if (gestureHub) {
1045                 TouchTestResult finalResult;
1046                 const auto coordinateOffset = globalPoint - localPoint;
1047                 preventBubbling = gestureHub->ProcessTouchTestHit(
1048                     coordinateOffset, touchRestrict, newComingTargets, finalResult, touchId);
1049                 newComingTargets.swap(finalResult);
1050             }
1051         } else if (touchRestrict.hitTestType == SourceType::MOUSE) {
1052             auto mouseHub = eventHub_->GetInputEventHub();
1053             if (mouseHub) {
1054                 const auto coordinateOffset = globalPoint - localPoint;
1055                 preventBubbling = mouseHub->ProcessMouseTestHit(coordinateOffset, newComingTargets);
1056             }
1057         }
1058     }
1059 
1060     result.splice(result.end(), std::move(newComingTargets));
1061     if (touchRestrict.hitTestType == SourceType::TOUCH) {
1062         // combine into exclusive recognizer group.
1063         auto gestureHub = eventHub_->GetGestureEventHub();
1064         if (gestureHub) {
1065             gestureHub->CombineIntoExclusiveRecognizer(globalPoint, localPoint, result, touchId);
1066         }
1067     }
1068 
1069     // consumed by children and return result.
1070     if (!consumed) {
1071         return testResult;
1072     }
1073 
1074     if (testResult == HitTestResult::OUT_OF_REGION) {
1075         // consume only by self.
1076         if (preventBubbling) {
1077             return HitTestResult::STOP_BUBBLING;
1078         }
1079         return (GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ? HitTestResult::SELF_TRANSPARENT
1080                                                                       : HitTestResult::BUBBLING;
1081     }
1082     // consume by self and children.
1083     return testResult;
1084 }
1085 
GetResponseRegionList(const RectF & rect)1086 std::vector<RectF> FrameNode::GetResponseRegionList(const RectF& rect)
1087 {
1088     std::vector<RectF> responseRegionList;
1089     auto gestureHub = eventHub_->GetGestureEventHub();
1090     if (!gestureHub) {
1091         responseRegionList.emplace_back(rect);
1092         return responseRegionList;
1093     }
1094 
1095     if (gestureHub->GetResponseRegion().empty()) {
1096         responseRegionList.emplace_back(rect);
1097         return responseRegionList;
1098     }
1099 
1100     auto scaleProperty = ScaleProperty::CreateScaleProperty();
1101     for (const auto& region : gestureHub->GetResponseRegion()) {
1102         auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
1103         auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
1104         auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
1105         auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
1106         RectF responseRegion(
1107             rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(), height.value());
1108         responseRegionList.emplace_back(responseRegion);
1109     }
1110     return responseRegionList;
1111 }
1112 
InResponseRegionList(const PointF & parentLocalPoint,const std::vector<RectF> & responseRegionList) const1113 bool FrameNode::InResponseRegionList(const PointF& parentLocalPoint, const std::vector<RectF>& responseRegionList) const
1114 {
1115     for (const auto& rect : responseRegionList) {
1116         if (rect.IsInRegion(parentLocalPoint)) {
1117             return true;
1118         }
1119     }
1120     return false;
1121 }
1122 
MouseTest(const PointF & globalPoint,const PointF & parentLocalPoint,MouseTestResult & onMouseResult,MouseTestResult & onHoverResult,RefPtr<FrameNode> & hoverNode)1123 HitTestResult FrameNode::MouseTest(const PointF& globalPoint, const PointF& parentLocalPoint,
1124     MouseTestResult& onMouseResult, MouseTestResult& onHoverResult, RefPtr<FrameNode>& hoverNode)
1125 {
1126     // unuseable function. do nothing.
1127     return HitTestResult::BUBBLING;
1128 }
1129 
AxisTest(const PointF & globalPoint,const PointF & parentLocalPoint,AxisTestResult & onAxisResult)1130 HitTestResult FrameNode::AxisTest(
1131     const PointF& globalPoint, const PointF& parentLocalPoint, AxisTestResult& onAxisResult)
1132 {
1133     const auto& rect = renderContext_->GetPaintRectWithTransform();
1134     LOGD("AxisTest: type is %{public}s, the region is %{public}lf, %{public}lf, %{public}lf, %{public}lf",
1135         GetTag().c_str(), rect.Left(), rect.Top(), rect.Width(), rect.Height());
1136     // TODO: disableTouchEvent || disabled_ need handle
1137 
1138     // TODO: Region need change to RectList
1139     if (!rect.IsInRegion(parentLocalPoint)) {
1140         return HitTestResult::OUT_OF_REGION;
1141     }
1142 
1143     bool preventBubbling = false;
1144 
1145     const auto localPoint = parentLocalPoint - rect.GetOffset();
1146     const auto& children = GetChildren();
1147     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
1148         auto& child = *iter;
1149         auto childHitResult = child->AxisTest(globalPoint, localPoint, onAxisResult);
1150         if (childHitResult == HitTestResult::STOP_BUBBLING) {
1151             preventBubbling = true;
1152         }
1153         // In normal process, the node block the brother node.
1154         if (childHitResult == HitTestResult::BUBBLING) {
1155             // TODO: add hit test mode judge.
1156             break;
1157         }
1158     }
1159 
1160     AxisTestResult axisResult;
1161     bool isPrevent = false;
1162     auto inputHub = eventHub_->GetInputEventHub();
1163     if (inputHub) {
1164         const auto coordinateOffset = globalPoint - localPoint;
1165         isPrevent = inputHub->ProcessAxisTestHit(coordinateOffset, axisResult);
1166     }
1167 
1168     if (!preventBubbling) {
1169         preventBubbling = isPrevent;
1170         onAxisResult.splice(onAxisResult.end(), std::move(axisResult));
1171     }
1172     if (preventBubbling) {
1173         return HitTestResult::STOP_BUBBLING;
1174     }
1175     return HitTestResult::BUBBLING;
1176 }
1177 
AnimateHoverEffect(bool isHovered) const1178 void FrameNode::AnimateHoverEffect(bool isHovered) const
1179 {
1180     auto renderContext = GetRenderContext();
1181     if (!renderContext) {
1182         return;
1183     }
1184     HoverEffectType animationType = HoverEffectType::UNKNOWN;
1185     auto inputEventHub = eventHub_->GetInputEventHub();
1186     if (inputEventHub) {
1187         animationType = inputEventHub->GetHoverEffect();
1188         if (animationType == HoverEffectType::UNKNOWN || animationType == HoverEffectType::AUTO) {
1189             animationType = inputEventHub->GetHoverEffectAuto();
1190         }
1191     }
1192     if (animationType == HoverEffectType::SCALE) {
1193         renderContext->AnimateHoverEffectScale(isHovered);
1194     } else if (animationType == HoverEffectType::BOARD) {
1195         renderContext->AnimateHoverEffectBoard(isHovered);
1196     }
1197 }
1198 
GetOrCreateFocusHub() const1199 RefPtr<FocusHub> FrameNode::GetOrCreateFocusHub() const
1200 {
1201     if (!pattern_) {
1202         return eventHub_->GetOrCreateFocusHub();
1203     }
1204     return eventHub_->GetOrCreateFocusHub(pattern_->GetFocusPattern().GetFocusType(),
1205         pattern_->GetFocusPattern().GetFocusable(), pattern_->GetFocusPattern().GetStyleType(),
1206         pattern_->GetFocusPattern().GetFocusPaintParams());
1207 }
1208 
OnWindowShow()1209 void FrameNode::OnWindowShow()
1210 {
1211     pattern_->OnWindowShow();
1212 }
1213 
OnWindowHide()1214 void FrameNode::OnWindowHide()
1215 {
1216     pattern_->OnWindowHide();
1217 }
1218 
OnWindowFocused()1219 void FrameNode::OnWindowFocused()
1220 {
1221     pattern_->OnWindowFocused();
1222 }
1223 
OnWindowUnfocused()1224 void FrameNode::OnWindowUnfocused()
1225 {
1226     pattern_->OnWindowUnfocused();
1227 }
1228 
GetOffsetRelativeToWindow() const1229 OffsetF FrameNode::GetOffsetRelativeToWindow() const
1230 {
1231     auto offset = geometryNode_->GetFrameOffset();
1232     auto parent = GetAncestorNodeOfFrame();
1233     if (renderContext_ && renderContext_->GetPositionProperty()) {
1234         if (renderContext_->GetPositionProperty()->HasPosition()) {
1235             offset.SetX(static_cast<float>(renderContext_->GetPositionProperty()->GetPosition()->GetX().Value()));
1236             offset.SetY(static_cast<float>(renderContext_->GetPositionProperty()->GetPosition()->GetY().Value()));
1237         }
1238     }
1239     while (parent) {
1240         auto parentRenderContext = parent->GetRenderContext();
1241         if (parentRenderContext && parentRenderContext->GetPositionProperty()) {
1242             if (parentRenderContext->GetPositionProperty()->HasPosition()) {
1243                 offset.AddX(
1244                     static_cast<float>(parentRenderContext->GetPositionProperty()->GetPosition()->GetX().Value()));
1245                 offset.AddY(
1246                     static_cast<float>(parentRenderContext->GetPositionProperty()->GetPosition()->GetY().Value()));
1247                 parent = parent->GetAncestorNodeOfFrame();
1248                 continue;
1249             }
1250         }
1251 
1252         offset += parent->geometryNode_->GetFrameOffset();
1253         parent = parent->GetAncestorNodeOfFrame();
1254     }
1255 
1256     return offset;
1257 }
1258 
GetTransformRectRelativeToWindow() const1259 RectF FrameNode::GetTransformRectRelativeToWindow() const
1260 {
1261     auto context = GetRenderContext();
1262     CHECK_NULL_RETURN(context, RectF());
1263     RectF rect = context->GetPaintRectWithTransform();
1264     auto offset = rect.GetOffset();
1265     auto parent = GetAncestorNodeOfFrame();
1266     while (parent) {
1267         auto parentRenderContext = parent->GetRenderContext();
1268         CHECK_NULL_RETURN(parentRenderContext, rect);
1269         auto parentScale = parentRenderContext->GetTransformScale();
1270         if (parentScale) {
1271             auto oldSize = rect.GetSize();
1272             auto newSize = SizeF(oldSize.Width() * parentScale.value().x, oldSize.Height() * parentScale.value().y);
1273             rect.SetSize(newSize);
1274 
1275             offset = OffsetF(offset.GetX() * parentScale.value().x, offset.GetY() * parentScale.value().y);
1276         }
1277 
1278         offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
1279 
1280         parent = parent->GetAncestorNodeOfFrame();
1281     }
1282     rect.SetOffset(offset);
1283     return rect;
1284 }
1285 
GetTransformRelativeOffset() const1286 OffsetF FrameNode::GetTransformRelativeOffset() const
1287 {
1288     auto context = GetRenderContext();
1289     CHECK_NULL_RETURN(context, OffsetF());
1290     auto offset = context->GetPaintRectWithTransform().GetOffset();
1291     auto parent = GetAncestorNodeOfFrame();
1292 
1293     while (parent) {
1294         auto parentRenderContext = parent->GetRenderContext();
1295         offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
1296         parent = parent->GetAncestorNodeOfFrame();
1297     }
1298 
1299     return offset;
1300 }
1301 
GetPaintRectOffset() const1302 OffsetF FrameNode::GetPaintRectOffset() const
1303 {
1304     auto context = GetRenderContext();
1305     CHECK_NULL_RETURN(context, OffsetF());
1306     auto offset = context->GetPaintRectWithTransform().GetOffset();
1307     auto parent = GetAncestorNodeOfFrame();
1308     while (parent) {
1309         auto renderContext = parent->GetRenderContext();
1310         CHECK_NULL_RETURN(renderContext, OffsetF());
1311         offset += renderContext->GetPaintRectWithTransform().GetOffset();
1312         parent = parent->GetAncestorNodeOfFrame();
1313     }
1314     return offset;
1315 }
1316 
GetPaintRectOffsetToPage() const1317 OffsetF FrameNode::GetPaintRectOffsetToPage() const
1318 {
1319     auto context = GetRenderContext();
1320     CHECK_NULL_RETURN(context, OffsetF());
1321     OffsetF offset = context->GetPaintRectWithTransform().GetOffset();
1322     auto parent = GetAncestorNodeOfFrame();
1323     while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
1324         auto renderContext = parent->GetRenderContext();
1325         CHECK_NULL_RETURN(renderContext, OffsetF());
1326         offset += renderContext->GetPaintRectWithTransform().GetOffset();
1327         parent = parent->GetAncestorNodeOfFrame();
1328     }
1329     return (parent && parent->GetTag() == V2::PAGE_ETS_TAG) ? offset : OffsetF();
1330 }
1331 
OnNotifyMemoryLevel(int32_t level)1332 void FrameNode::OnNotifyMemoryLevel(int32_t level)
1333 {
1334     pattern_->OnNotifyMemoryLevel(level);
1335 }
1336 
GetAllDepthChildrenCount()1337 int32_t FrameNode::GetAllDepthChildrenCount()
1338 {
1339     int32_t result = 0;
1340     std::list<RefPtr<FrameNode>> children;
1341     children.emplace_back(Claim(this));
1342     while (!children.empty()) {
1343         auto& node = children.front();
1344         if (!node->IsInternal()) {
1345             result++;
1346             node->GenerateOneDepthVisibleFrame(children);
1347         }
1348         children.pop_front();
1349     }
1350     return result;
1351 }
1352 
OnAccessibilityEvent(AccessibilityEventType eventType) const1353 void FrameNode::OnAccessibilityEvent(AccessibilityEventType eventType) const
1354 {
1355     if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
1356         AccessibilityEvent event;
1357         event.type = eventType;
1358         event.nodeId = GetAccessibilityId();
1359         PipelineContext::GetCurrentContext()->SendEventToAccessibility(event);
1360     }
1361 }
1362 
AddHotZoneRect(const DimensionRect & hotZoneRect) const1363 void FrameNode::AddHotZoneRect(const DimensionRect& hotZoneRect) const
1364 {
1365     auto gestureHub = GetOrCreateGestureEventHub();
1366     gestureHub->AddResponseRect(hotZoneRect);
1367 }
1368 
RemoveLastHotZoneRect() const1369 void FrameNode::RemoveLastHotZoneRect() const
1370 {
1371     auto gestureHub = GetOrCreateGestureEventHub();
1372     gestureHub->RemoveLastResponseRect();
1373 }
1374 
1375 } // namespace OHOS::Ace::NG
1376