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