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