1 /*
2 * Copyright (c) 2022-2024 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 <cstdint>
19
20 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
21 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
22 #include "frameworks/core/components_ng/pattern/web/web_pattern.h"
23 #endif
24 #include "base/geometry/ng/rect_t.h"
25 #include "core/pipeline/base/element_register.h"
26 #include "base/geometry/dimension.h"
27 #include "base/geometry/ng/offset_t.h"
28 #include "base/geometry/ng/point_t.h"
29 #include "base/log/ace_performance_monitor.h"
30 #include "base/log/ace_trace.h"
31 #include "base/log/dump_log.h"
32 #include "base/log/log_wrapper.h"
33 #include "base/memory/ace_type.h"
34 #include "base/memory/referenced.h"
35 #include "base/thread/cancelable_callback.h"
36 #include "base/thread/task_executor.h"
37 #include "base/utils/system_properties.h"
38 #include "base/utils/time_util.h"
39 #include "base/utils/utils.h"
40 #include "core/common/ace_application_info.h"
41 #include "core/common/container.h"
42 #include "core/common/recorder/event_recorder.h"
43 #include "core/common/recorder/node_data_cache.h"
44 #include "core/common/stylus/stylus_detector_mgr.h"
45 #include "core/components/common/layout/constants.h"
46 #include "core/components/common/layout/grid_system_manager.h"
47 #include "core/components_ng/base/extension_handler.h"
48 #include "core/components_ng/base/frame_scene_status.h"
49 #include "core/components_ng/base/inspector.h"
50 #include "core/components_ng/base/inspector_filter.h"
51 #include "core/components_ng/base/ui_node.h"
52 #include "core/components_ng/event/drag_event.h"
53 #include "core/components_ng/event/gesture_event_hub.h"
54 #include "core/components_ng/event/target_component.h"
55 #include "core/components_ng/gestures/recognizers/multi_fingers_recognizer.h"
56 #include "core/components_ng/layout/layout_algorithm.h"
57 #include "core/components_ng/layout/layout_wrapper.h"
58 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
59 #include "core/components_ng/pattern/pattern.h"
60 #include "core/components_ng/pattern/stage/page_pattern.h"
61 #include "core/components_ng/property/measure_property.h"
62 #include "core/components_ng/property/measure_utils.h"
63 #include "core/components_ng/property/property.h"
64 #include "core/components_ng/render/paint_wrapper.h"
65 #include "core/components_ng/syntax/lazy_for_each_node.h"
66 #include "core/components_ng/syntax/repeat_virtual_scroll_node.h"
67 #include "core/components_v2/inspector/inspector_constants.h"
68 #include "core/event/touch_event.h"
69 #include "core/gestures/gesture_info.h"
70 #include "core/pipeline_ng/pipeline_context.h"
71 #include "core/pipeline_ng/ui_task_scheduler.h"
72
73 namespace {
74 constexpr double VISIBLE_RATIO_MIN = 0.0;
75 constexpr double VISIBLE_RATIO_MAX = 1.0;
76 constexpr int32_t SUBSTR_LENGTH = 3;
77 const char DIMENSION_UNIT_VP[] = "vp";
78 constexpr int32_t SIZE_CHANGE_DUMP_SIZE = 5;
79 constexpr double MIN_WIDTH = 5.0;
80 constexpr double MIN_HEIGHT = 5.0;
81 constexpr double MIN_OPACITY = 0.1;
82 constexpr uint64_t MATRIX_CACHE_TIME_THRESHOLD = 15000000000;
83 /* suggestOpIncByte_s status mask, to indicate different aspects of node status
84 * related with suggestion OPINC improvements.
85 * for internal use; subject to change.
86 */
87 // suggest opinc marked.
88 constexpr uint8_t SUGGEST_OPINC_MARKED_MASK = 1;
89 // Whether the node can be suggest opinc marked.
90 constexpr uint8_t CAN_SUGGEST_OPINC_MASK = 1 << 1;
91 // The node already activated for suggest opinc.
92 constexpr uint8_t SUGGEST_OPINC_ACTIVATED_ONCE = 1 << 2;
93 // The node already checked for suggest opinc.
94 constexpr uint8_t SUGGEST_OPINC_CHCKED_ONCE = 1 << 3;
95 // The node has checked through for lazy new nodes.
96 constexpr uint8_t SUGGEST_OPINC_CHECKED_THROUGH = 1 << 4;
97 // Node has rendergroup marked.
98 constexpr uint8_t APP_RENDER_GROUP_MARKED_MASK = 1 << 7;
99 // OPINC must more then 2 leaf;
100 constexpr int32_t THRESH_CHILD_NO = 2;
101 // OPINC max ratio for scroll scope(height);
102 constexpr float HIGHT_RATIO_LIMIT = 0.8;
103 // Min area for OPINC
104 constexpr int32_t MIN_OPINC_AREA = 10000;
105 constexpr char UPDATE_FLAG_KEY[] = "updateFlag";
106 constexpr int32_t DEFAULT_PRECISION = 2;
107 } // namespace
108 namespace OHOS::Ace::NG {
109
110 const std::set<std::string> FrameNode::layoutTags_ = { "Flex", "Stack", "Row", "Column", "WindowScene", "root",
111 "__Common__", "Swiper", "Grid", "GridItem", "page", "stage", "FormComponent", "Tabs", "TabContent" };
112
113 class FrameNode::FrameProxy final : public RecursiveLock {
114 public:
115 struct FrameChildNode {
116 RefPtr<UINode> node;
117 uint32_t startIndex = 0;
118 uint32_t count = 0;
119 };
120
Lock()121 void Lock() override
122 {
123 ++inUse_;
124 }
125
Unlock()126 void Unlock() override
127 {
128 --inUse_;
129 if (!inUse_ && delayReset_) {
130 auto it = &hostNode_->frameProxy_;
131 while ((*it)) {
132 if (this == (*it)->prevFrameProxy_.get()) {
133 auto me = std::move((*it)->prevFrameProxy_);
134 (*it)->prevFrameProxy_ = std::move(me->prevFrameProxy_);
135 break;
136 }
137 it = &(*it)->prevFrameProxy_;
138 }
139 }
140 }
141
GetGuard()142 RecursionGuard GetGuard()
143 {
144 return RecursionGuard(*this);
145 }
146
FrameProxy(FrameNode * frameNode)147 explicit FrameProxy(FrameNode* frameNode) : hostNode_(frameNode)
148 {
149 prevFrameProxy_ = std::move(hostNode_->frameProxy_);
150 if (prevFrameProxy_ && !prevFrameProxy_->needResetChild_) {
151 children_ = prevFrameProxy_->children_;
152 cursor_ = children_.end();
153 if (prevFrameProxy_->cursor_ != prevFrameProxy_->children_.end()) {
154 cursor_ = std::find_if(children_.begin(), children_.end(),
155 [this](FrameChildNode& node) { return prevFrameProxy_->cursor_->node == node.node; });
156 }
157 }
158 }
159
Build()160 void Build()
161 {
162 if (hostNode_ == nullptr || !children_.empty()) {
163 return;
164 }
165 totalCount_ = 0;
166 auto children = hostNode_->GetChildren();
167 int32_t startIndex = 0;
168 int32_t count = 0;
169 for (const auto& child : children) {
170 count = child->FrameCount();
171 child->SetNodeIndexOffset(startIndex, count);
172 children_.push_back({ child, startIndex, count });
173 startIndex += count;
174 totalCount_ += count;
175 }
176 cursor_ = children_.begin();
177 }
178
AddFrameNode(const RefPtr<UINode> & UiNode,std::list<RefPtr<LayoutWrapper>> & allFrameNodeChildren,std::map<uint32_t,RefPtr<LayoutWrapper>> & partFrameNodeChildren,uint32_t & count)179 static void AddFrameNode(const RefPtr<UINode>& UiNode, std::list<RefPtr<LayoutWrapper>>& allFrameNodeChildren,
180 std::map<uint32_t, RefPtr<LayoutWrapper>>& partFrameNodeChildren, uint32_t& count)
181 {
182 auto frameNode = AceType::DynamicCast<FrameNode>(UiNode);
183 if (frameNode) {
184 allFrameNodeChildren.emplace_back(frameNode);
185 partFrameNodeChildren[count++] = frameNode;
186 return;
187 }
188 auto lazyForEachNode = AceType::DynamicCast<LazyForEachNode>(UiNode);
189 auto repeatVirtualScrollNode = AceType::DynamicCast<RepeatVirtualScrollNode>(UiNode);
190 if (lazyForEachNode) {
191 lazyForEachNode->BuildAllChildren();
192 } else if (repeatVirtualScrollNode) {
193 TAG_LOGE(AceLogTag::ACE_REPEAT, "repeatVirtualScroll not support in non scoll container!");
194 } else {
195 auto customNode = AceType::DynamicCast<CustomNode>(UiNode);
196 if (customNode) {
197 customNode->Render();
198 }
199 }
200 for (const auto& child : UiNode->GetChildren()) {
201 auto frameNode = AceType::DynamicCast<FrameNode>(child);
202 if (frameNode) {
203 allFrameNodeChildren.emplace_back(frameNode);
204 partFrameNodeChildren[count++] = frameNode;
205 continue;
206 }
207 AddFrameNode(child, allFrameNodeChildren, partFrameNodeChildren, count);
208 }
209 }
210
GetAllFrameChildren()211 ChildrenListWithGuard GetAllFrameChildren()
212 {
213 auto guard = GetGuard();
214 if (allFrameNodeChildren_.empty()) {
215 Build();
216 uint32_t count = 0;
217 for (const auto& child : children_) {
218 AddFrameNode(child.node, allFrameNodeChildren_, partFrameNodeChildren_, count);
219 }
220 }
221 return ChildrenListWithGuard(allFrameNodeChildren_, *this);
222 }
223
GetCurrentFrameChildren()224 ChildrenListWithGuard GetCurrentFrameChildren()
225 {
226 auto guard = GetGuard();
227 return ChildrenListWithGuard(allFrameNodeChildren_, *this);
228 }
229
FindFrameNodeByIndex(uint32_t index,bool needBuild,bool isCache,bool addToRenderTree)230 RefPtr<LayoutWrapper> FindFrameNodeByIndex(uint32_t index, bool needBuild, bool isCache, bool addToRenderTree)
231 {
232 while (cursor_ != children_.end()) {
233 if (cursor_->startIndex > index) {
234 cursor_--;
235 continue;
236 }
237
238 if (cursor_->startIndex + cursor_->count > index) {
239 auto frameNode = AceType::DynamicCast<FrameNode>(cursor_->node->GetFrameChildByIndex(
240 index - cursor_->startIndex, needBuild, isCache, addToRenderTree));
241 return frameNode;
242 }
243 cursor_++;
244 if (cursor_ == children_.end()) {
245 cursor_ = children_.begin();
246 return nullptr;
247 }
248 }
249 return nullptr;
250 }
251
GetFrameNodeByIndex(uint32_t index,bool needBuild,bool isCache,bool addToRenderTree)252 RefPtr<LayoutWrapper> GetFrameNodeByIndex(uint32_t index, bool needBuild, bool isCache, bool addToRenderTree)
253 {
254 auto itor = partFrameNodeChildren_.find(index);
255 if (itor == partFrameNodeChildren_.end()) {
256 Build();
257 auto child = FindFrameNodeByIndex(index, needBuild, isCache, addToRenderTree);
258 if (child && !isCache) {
259 partFrameNodeChildren_[index] = child;
260 }
261 return child;
262 }
263 return itor->second;
264 }
265
266 /**
267 * @brief Find child's index in parent's map. Only works on children that are already created and recorded.
268 *
269 * @param target child LayoutWrapper
270 * @return index of children
271 */
GetChildIndex(const RefPtr<LayoutWrapper> & target) const272 int32_t GetChildIndex(const RefPtr<LayoutWrapper>& target) const
273 {
274 for (auto it : partFrameNodeChildren_) {
275 if (it.second == target) {
276 return it.first;
277 }
278 }
279 return -1;
280 }
281
ResetChildren(bool needResetChild=false)282 void ResetChildren(bool needResetChild = false)
283 {
284 if (inUse_) {
285 LOGF(
286 "[%{public}d:%{public}s] reset children while in use", hostNode_->GetId(), hostNode_->GetTag().c_str());
287 if (SystemProperties::GetLayoutDetectEnabled()) {
288 abort();
289 }
290 delayReset_ = true;
291 needResetChild_ = needResetChild;
292 hostNode_->frameProxy_ = std::make_unique<FrameProxy>(hostNode_);
293 return;
294 }
295 auto guard = GetGuard();
296 delayReset_ = false;
297 allFrameNodeChildren_.clear();
298 partFrameNodeChildren_.clear();
299 totalCount_ = 0;
300 if (needResetChild) {
301 children_.clear();
302 cursor_ = children_.begin();
303 }
304 }
305
RemoveChildInRenderTree(uint32_t index)306 void RemoveChildInRenderTree(uint32_t index)
307 {
308 auto itor = partFrameNodeChildren_.find(index);
309 if (itor == partFrameNodeChildren_.end()) {
310 return;
311 }
312 itor->second->SetActive(false);
313 partFrameNodeChildren_.erase(itor);
314 while (cursor_ != children_.end()) {
315 if (cursor_->startIndex > index) {
316 cursor_--;
317 continue;
318 }
319 if (cursor_->startIndex + cursor_->count > index) {
320 cursor_->node->DoRemoveChildInRenderTree(index - cursor_->startIndex);
321 return;
322 }
323 cursor_++;
324 if (cursor_ == children_.end()) {
325 cursor_ = children_.begin();
326 return;
327 }
328 }
329 }
330
SetActiveChildRange(int32_t start,int32_t end,int32_t cacheStart,int32_t cacheEnd)331 void SetActiveChildRange(int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd)
332 {
333 for (auto itor = partFrameNodeChildren_.begin(); itor != partFrameNodeChildren_.end();) {
334 int32_t index = itor->first;
335 if ((start <= end && index >= start && index <= end) || (start > end && (index <= end || start <= index))) {
336 itor++;
337 } else {
338 itor = partFrameNodeChildren_.erase(itor);
339 }
340 }
341 auto guard = GetGuard();
342 for (const auto& child : children_) {
343 child.node->DoSetActiveChildRange(start - child.startIndex, end - child.startIndex, cacheStart, cacheEnd);
344 }
345 }
346
SetActiveChildRange(const std::optional<ActiveChildSets> & activeChildSets,const std::optional<ActiveChildRange> & activeChildRange)347 void SetActiveChildRange(
348 const std::optional<ActiveChildSets>& activeChildSets, const std::optional<ActiveChildRange>& activeChildRange)
349 {
350 if (!activeChildSets.has_value()) {
351 return;
352 }
353 for (auto itor = partFrameNodeChildren_.begin(); itor != partFrameNodeChildren_.end();) {
354 int32_t index = itor->first;
355 if (activeChildSets->activeItems.find(index) != activeChildSets->activeItems.end()) {
356 itor++;
357 } else {
358 itor = partFrameNodeChildren_.erase(itor);
359 }
360 }
361 auto guard = GetGuard();
362 // repeat node will use active node sets, V1 node(as lazyforeach) will still use active ndoe range.
363 for (const auto& child : children_) {
364 if (child.node->GetTag() == V2::JS_REPEAT_ETS_TAG) {
365 child.node->DoSetActiveChildRange(
366 activeChildSets->activeItems, activeChildSets->cachedItems, child.startIndex);
367 } else if (activeChildRange.has_value()) {
368 child.node->DoSetActiveChildRange(activeChildRange->start - child.startIndex,
369 activeChildRange->end - child.startIndex, activeChildRange->cacheStart, activeChildRange->cacheEnd);
370 }
371 }
372 }
373
RecycleItemsByIndex(uint32_t start,uint32_t end)374 void RecycleItemsByIndex(uint32_t start, uint32_t end)
375 {
376 for (auto it = partFrameNodeChildren_.begin(); it != partFrameNodeChildren_.end();) {
377 if (it->first >= start && it->first < end) {
378 it = partFrameNodeChildren_.erase(it);
379 } else {
380 it++;
381 }
382 }
383 }
384
RemoveAllChildInRenderTreeAfterReset()385 void RemoveAllChildInRenderTreeAfterReset()
386 {
387 Build();
388 auto guard = GetGuard();
389 for (const auto& child : children_) {
390 child.node->DoRemoveChildInRenderTree(0, true);
391 }
392 }
393
RemoveAllChildInRenderTree()394 void RemoveAllChildInRenderTree()
395 {
396 SetAllChildrenInactive();
397 ResetChildren();
398 hostNode_->frameProxy_->RemoveAllChildInRenderTreeAfterReset();
399 }
400
GetTotalCount()401 uint32_t GetTotalCount()
402 {
403 return totalCount_;
404 }
405
SetAllChildrenInactive()406 void SetAllChildrenInactive()
407 {
408 auto guard = GetGuard();
409 for (const auto& child : partFrameNodeChildren_) {
410 child.second->SetActive(false);
411 }
412 }
413
Dump()414 std::string Dump()
415 {
416 if (totalCount_ == 0) {
417 return "totalCount is 0";
418 }
419 std::string info = "FrameChildNode:[";
420 auto guard = GetGuard();
421 for (const auto& child : children_) {
422 info += std::to_string(child.node->GetId());
423 info += "-";
424 info += std::to_string(child.startIndex);
425 info += "-";
426 info += std::to_string(child.count);
427 info += ",";
428 }
429 info += "] partFrameNodeChildren:[";
430 for (const auto& child : partFrameNodeChildren_) {
431 info += std::to_string(child.second->GetHostNode()->GetId());
432 info += ",";
433 }
434 info += "] TotalCount:";
435 info += std::to_string(totalCount_);
436 return info;
437 }
438
SetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)439 void SetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
440 {
441 auto guard = GetGuard();
442 for (const auto& child : children_) {
443 child.node->OnSetCacheCount(cacheCount, itemConstraint);
444 }
445 }
446
447 private:
448 std::list<FrameChildNode> children_;
449 std::list<FrameChildNode>::iterator cursor_ = children_.begin();
450 std::list<RefPtr<LayoutWrapper>> allFrameNodeChildren_;
451 std::map<uint32_t, RefPtr<LayoutWrapper>> partFrameNodeChildren_;
452 std::unique_ptr<FrameProxy> prevFrameProxy_;
453 int32_t totalCount_ = 0;
454 FrameNode* hostNode_ { nullptr };
455 uint32_t inUse_ = 0;
456 bool delayReset_ = false;
457 bool needResetChild_ = false;
458 }; // namespace OHOS::Ace::NG
459
FrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot,bool isLayoutNode)460 FrameNode::FrameNode(
461 const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot, bool isLayoutNode)
462 : UINode(tag, nodeId, isRoot), LayoutWrapper(WeakClaim(this)), pattern_(pattern)
463 {
464 isLayoutNode_ = isLayoutNode;
465 frameProxy_ = std::make_unique<FrameProxy>(this);
466 renderContext_->InitContext(IsRootNode(), pattern_->GetContextParam(), isLayoutNode);
467 paintProperty_ = pattern->CreatePaintProperty();
468 layoutProperty_ = pattern->CreateLayoutProperty();
469 eventHub_ = pattern->CreateEventHub();
470 accessibilityProperty_ = pattern->CreateAccessibilityProperty();
471 // first create make layout property dirty.
472 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
473 layoutProperty_->SetHost(WeakClaim(this));
474 layoutSeperately_ = true;
475 }
476
~FrameNode()477 FrameNode::~FrameNode()
478 {
479 ResetPredictNodes();
480 for (const auto& destroyCallback : destroyCallbacks_) {
481 destroyCallback();
482 }
483 for (const auto& destroyCallback : destroyCallbacksMap_) {
484 if (destroyCallback.second) {
485 destroyCallback.second();
486 }
487 }
488 if (removeCustomProperties_) {
489 removeCustomProperties_();
490 removeCustomProperties_ = nullptr;
491 }
492
493 pattern_->DetachFromFrameNode(this);
494 if (IsOnMainTree()) {
495 OnDetachFromMainTree(false, GetContextWithCheck());
496 }
497 TriggerVisibleAreaChangeCallback(0, true);
498 CleanVisibleAreaUserCallback();
499 CleanVisibleAreaInnerCallback();
500 if (eventHub_) {
501 eventHub_->ClearOnAreaChangedInnerCallbacks();
502 }
503 auto pipeline = PipelineContext::GetCurrentContext();
504 if (pipeline) {
505 pipeline->RemoveOnAreaChangeNode(GetId());
506 pipeline->RemoveVisibleAreaChangeNode(GetId());
507 pipeline->ChangeMouseStyle(GetId(), MouseFormat::DEFAULT);
508 pipeline->FreeMouseStyleHoldNode(GetId());
509 pipeline->RemoveStoredNode(GetRestoreId());
510 auto dragManager = pipeline->GetDragDropManager();
511 if (dragManager) {
512 dragManager->RemoveDragFrameNode(GetId());
513 dragManager->UnRegisterDragStatusListener(GetId());
514 }
515 auto frameRateManager = pipeline->GetFrameRateManager();
516 if (frameRateManager) {
517 frameRateManager->RemoveNodeRate(GetId());
518 }
519 pipeline->RemoveChangedFrameNode(GetId());
520 pipeline->RemoveFrameNodeChangeListener(GetId());
521 }
522 FireOnNodeDestroyCallback();
523 }
524
CreateFrameNodeWithTree(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern)525 RefPtr<FrameNode> FrameNode::CreateFrameNodeWithTree(
526 const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern)
527 {
528 auto newChild = CreateFrameNode(tag, nodeId, pattern, true);
529 newChild->SetDepth(1);
530 return newChild;
531 }
532
GetOrCreateFrameNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)533 RefPtr<FrameNode> FrameNode::GetOrCreateFrameNode(
534 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
535 {
536 auto frameNode = GetFrameNode(tag, nodeId);
537 if (frameNode) {
538 return frameNode;
539 }
540 auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
541 return CreateFrameNode(tag, nodeId, pattern);
542 }
543
GetOrCreateCommonNode(const std::string & tag,int32_t nodeId,bool isLayoutNode,const std::function<RefPtr<Pattern> (void)> & patternCreator)544 RefPtr<FrameNode> FrameNode::GetOrCreateCommonNode(const std::string& tag, int32_t nodeId, bool isLayoutNode,
545 const std::function<RefPtr<Pattern>(void)>& patternCreator)
546 {
547 auto commonNode = GetFrameNode(tag, nodeId);
548 if (commonNode) {
549 commonNode->isLayoutNode_ = isLayoutNode;
550 return commonNode;
551 }
552 auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
553 return CreateCommonNode(tag, nodeId, isLayoutNode, pattern);
554 }
555
GetFrameNode(const std::string & tag,int32_t nodeId)556 RefPtr<FrameNode> FrameNode::GetFrameNode(const std::string& tag, int32_t nodeId)
557 {
558 auto frameNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(nodeId);
559 CHECK_NULL_RETURN(frameNode, nullptr);
560 if (frameNode->GetTag() != tag) {
561 ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
562 auto parent = frameNode->GetParent();
563 if (parent) {
564 parent->RemoveChild(frameNode);
565 }
566 return nullptr;
567 }
568 return frameNode;
569 }
570
CreateFrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)571 RefPtr<FrameNode> FrameNode::CreateFrameNode(
572 const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
573 {
574 auto frameNode = MakeRefPtr<FrameNode>(tag, nodeId, pattern, isRoot);
575 ElementRegister::GetInstance()->AddUINode(frameNode);
576 frameNode->InitializePatternAndContext();
577 return frameNode;
578 }
579
CreateCommonNode(const std::string & tag,int32_t nodeId,bool isLayoutNode,const RefPtr<Pattern> & pattern,bool isRoot)580 RefPtr<FrameNode> FrameNode::CreateCommonNode(
581 const std::string& tag, int32_t nodeId, bool isLayoutNode, const RefPtr<Pattern>& pattern, bool isRoot)
582 {
583 auto frameNode = MakeRefPtr<FrameNode>(tag, nodeId, pattern, isRoot, isLayoutNode);
584 ElementRegister::GetInstance()->AddUINode(frameNode);
585 frameNode->InitializePatternAndContext();
586 return frameNode;
587 }
588
GetIsLayoutNode()589 bool FrameNode::GetIsLayoutNode()
590 {
591 return isLayoutNode_;
592 }
593
GetIsFind()594 bool FrameNode::GetIsFind()
595 {
596 return isFind_;
597 }
598
SetIsFind(bool isFind)599 void FrameNode::SetIsFind(bool isFind)
600 {
601 isFind_ = isFind;
602 }
603
GetOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & children)604 void FrameNode::GetOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& children)
605 {
606 GenerateOneDepthVisibleFrameWithTransition(children);
607 if (overlayNode_) {
608 children.emplace_back(overlayNode_);
609 }
610 }
611
GetOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>> & children,OffsetF & offset)612 void FrameNode::GetOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>>& children, OffsetF& offset)
613 {
614 offset += GetGeometryNode()->GetFrameOffset();
615 GenerateOneDepthVisibleFrameWithOffset(children, offset);
616 if (overlayNode_) {
617 children.emplace_back(overlayNode_);
618 }
619 }
620
IsSupportDrawModifier()621 bool FrameNode::IsSupportDrawModifier()
622 {
623 CHECK_NULL_RETURN(pattern_, false);
624 return pattern_->IsSupportDrawModifier();
625 }
626
ProcessOffscreenNode(const RefPtr<FrameNode> & node)627 void FrameNode::ProcessOffscreenNode(const RefPtr<FrameNode>& node)
628 {
629 CHECK_NULL_VOID(node);
630 node->ProcessOffscreenTask();
631 node->MarkModifyDone();
632 node->UpdateLayoutPropertyFlag();
633 node->SetActive();
634 node->isLayoutDirtyMarked_ = true;
635 auto pipeline = PipelineContext::GetCurrentContext();
636 if (pipeline) {
637 pipeline->FlushUITaskWithSingleDirtyNode(node);
638 }
639 auto predictLayoutNode = std::move(node->predictLayoutNode_);
640 for (auto& node : predictLayoutNode) {
641 auto frameNode = node.Upgrade();
642 if (frameNode && pipeline) {
643 pipeline->FlushUITaskWithSingleDirtyNode(frameNode);
644 }
645 }
646 if (pipeline) {
647 pipeline->FlushSyncGeometryNodeTasks();
648 }
649
650 auto paintProperty = node->GetPaintProperty<PaintProperty>();
651 auto wrapper = node->CreatePaintWrapper();
652 if (wrapper != nullptr) {
653 wrapper->FlushRender();
654 }
655 paintProperty->CleanDirty();
656 CHECK_NULL_VOID(pipeline);
657 pipeline->FlushMessages();
658 node->SetActive(false);
659 }
660
InitializePatternAndContext()661 void FrameNode::InitializePatternAndContext()
662 {
663 eventHub_->AttachHost(WeakClaim(this));
664 pattern_->AttachToFrameNode(WeakClaim(this));
665 accessibilityProperty_->SetHost(WeakClaim(this));
666 renderContext_->SetRequestFrame([weak = WeakClaim(this)] {
667 auto frameNode = weak.Upgrade();
668 CHECK_NULL_VOID(frameNode);
669 if (frameNode->IsOnMainTree()) {
670 auto context = frameNode->GetContext();
671 CHECK_NULL_VOID(context);
672 context->RequestFrame();
673 return;
674 }
675 frameNode->hasPendingRequest_ = true;
676 });
677 renderContext_->SetHostNode(WeakClaim(this));
678 // Initialize FocusHub
679 if (pattern_->GetFocusPattern().GetFocusType() != FocusType::DISABLE) {
680 GetOrCreateFocusHub();
681 }
682 }
683
DumpSafeAreaInfo()684 void FrameNode::DumpSafeAreaInfo()
685 {
686 if (layoutProperty_->GetSafeAreaExpandOpts()) {
687 DumpLog::GetInstance().AddDesc(layoutProperty_->GetSafeAreaExpandOpts()->ToString());
688 }
689 if (layoutProperty_->GetSafeAreaInsets()) {
690 DumpLog::GetInstance().AddDesc(layoutProperty_->GetSafeAreaInsets()->ToString());
691 }
692 if (SelfOrParentExpansive()) {
693 DumpLog::GetInstance().AddDesc(std::string("selfAdjust: ")
694 .append(geometryNode_->GetSelfAdjust().ToString().c_str())
695 .append(",parentAdjust: ")
696 .append(geometryNode_->GetParentAdjust().ToString().c_str()));
697 }
698 CHECK_NULL_VOID(GetTag() == V2::PAGE_ETS_TAG);
699 auto pipeline = GetContext();
700 CHECK_NULL_VOID(pipeline);
701 auto manager = pipeline->GetSafeAreaManager();
702 CHECK_NULL_VOID(manager);
703 DumpLog::GetInstance().AddDesc(std::string("ignoreSafeArea: ")
704 .append(std::to_string(manager->IsIgnoreAsfeArea()))
705 .append(std::string(", isNeedAvoidWindow: ").c_str())
706 .append(std::to_string(manager->IsNeedAvoidWindow()))
707 .append(std::string(", isFullScreen: ").c_str())
708 .append(std::to_string(manager->IsFullScreen()))
709 .append(std::string(", isKeyboardAvoidMode").c_str())
710 .append(std::to_string(manager->KeyboardSafeAreaEnabled()))
711 .append(std::string(", isUseCutout").c_str())
712 .append(std::to_string(pipeline->GetUseCutout())));
713 }
714
DumpAlignRulesInfo()715 void FrameNode::DumpAlignRulesInfo()
716 {
717 auto& flexItemProperties = layoutProperty_->GetFlexItemProperty();
718 CHECK_NULL_VOID(flexItemProperties);
719 auto rulesToString = flexItemProperties->AlignRulesToString();
720 CHECK_NULL_VOID(!rulesToString.empty());
721 DumpLog::GetInstance().AddDesc(std::string("AlignRules: ").append(rulesToString));
722 }
723
DumpExtensionHandlerInfo()724 void FrameNode::DumpExtensionHandlerInfo()
725 {
726 if (!extensionHandler_) {
727 return;
728 }
729 DumpLog::GetInstance().AddDesc(std::string("ExtensionHandler: HasCustomerMeasure: ")
730 .append(extensionHandler_->HasCustomerMeasure() ? "true" : "false")
731 .append(", HasCustomerLayout: ")
732 .append(extensionHandler_->HasCustomerLayout() ? "true" : "false"));
733 }
734
DumpCommonInfo()735 void FrameNode::DumpCommonInfo()
736 {
737 DumpLog::GetInstance().AddDesc(std::string("FrameRect: ").append(geometryNode_->GetFrameRect().ToString()));
738 DumpLog::GetInstance().AddDesc(
739 std::string("PaintRect without transform: ").append(renderContext_->GetPaintRectWithoutTransform().ToString()));
740 if (renderContext_->GetBackgroundColor()->ColorToString().compare("#00000000") != 0) {
741 DumpLog::GetInstance().AddDesc(
742 std::string("BackgroundColor: ").append(renderContext_->GetBackgroundColor()->ColorToString()));
743 }
744 if (geometryNode_->GetParentLayoutConstraint().has_value()) {
745 DumpLog::GetInstance().AddDesc(std::string("ParentLayoutConstraint: ")
746 .append(geometryNode_->GetParentLayoutConstraint().value().ToString()));
747 }
748 DumpLog::GetInstance().AddDesc(std::string("top: ")
749 .append(std::to_string(GetOffsetRelativeToWindow().GetY()))
750 .append(" left: ")
751 .append(std::to_string(GetOffsetRelativeToWindow().GetX())));
752 if (static_cast<int32_t>(IsActive()) != 1) {
753 DumpLog::GetInstance().AddDesc(
754 std::string("Active: ").append(std::to_string(static_cast<int32_t>(IsActive()))));
755 }
756 if (IsFreeze()) {
757 DumpLog::GetInstance().AddDesc(std::string("Freeze: 1"));
758 }
759 if (static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)) != 0) {
760 DumpLog::GetInstance().AddDesc(std::string("Visible: ")
761 .append(std::to_string(static_cast<int32_t>(
762 layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)))));
763 }
764 if (layoutProperty_->GetPaddingProperty()) {
765 DumpLog::GetInstance().AddDesc(
766 std::string("Padding: ").append(layoutProperty_->GetPaddingProperty()->ToString().c_str()));
767 }
768 if (layoutProperty_->GetBorderWidthProperty()) {
769 DumpLog::GetInstance().AddDesc(
770 std::string("Border: ").append(layoutProperty_->GetBorderWidthProperty()->ToString().c_str()));
771 }
772 if (layoutProperty_->GetMarginProperty()) {
773 DumpLog::GetInstance().AddDesc(
774 std::string("Margin: ").append(layoutProperty_->GetMarginProperty()->ToString().c_str()));
775 }
776 if (layoutProperty_->GetLayoutRect()) {
777 DumpLog::GetInstance().AddDesc(
778 std::string("LayoutRect: ").append(layoutProperty_->GetLayoutRect().value().ToString().c_str()));
779 }
780 DumpExtensionHandlerInfo();
781 DumpSafeAreaInfo();
782 if (layoutProperty_->GetCalcLayoutConstraint()) {
783 DumpLog::GetInstance().AddDesc(std::string("User defined constraint: ")
784 .append(layoutProperty_->GetCalcLayoutConstraint()->ToString().c_str()));
785 }
786 if (!propInspectorId_->empty()) {
787 DumpLog::GetInstance().AddDesc(std::string("compid: ").append(propInspectorId_.value_or("")));
788 }
789 if (layoutProperty_->GetPaddingProperty() || layoutProperty_->GetBorderWidthProperty() ||
790 layoutProperty_->GetMarginProperty() || layoutProperty_->GetCalcLayoutConstraint()) {
791 DumpLog::GetInstance().AddDesc(
792 std::string("ContentConstraint: ")
793 .append(layoutProperty_->GetContentLayoutConstraint().has_value()
794 ? layoutProperty_->GetContentLayoutConstraint().value().ToString()
795 : "NA"));
796 }
797 DumpAlignRulesInfo();
798 DumpDragInfo();
799 DumpOverlayInfo();
800 if (frameProxy_->Dump().compare("totalCount is 0") != 0) {
801 DumpLog::GetInstance().AddDesc(std::string("FrameProxy: ").append(frameProxy_->Dump().c_str()));
802 }
803 if (isRemoving_) {
804 DumpLog::GetInstance().AddDesc(std::string("IsRemoving: True"));
805 }
806 }
807
DumpDragInfo()808 void FrameNode::DumpDragInfo()
809 {
810 DumpLog::GetInstance().AddDesc("------------start print dragInfo");
811 DumpLog::GetInstance().AddDesc(std::string("Draggable: ")
812 .append(draggable_ ? "true" : "false")
813 .append(" UserSet: ")
814 .append(userSet_ ? "true" : "false")
815 .append(" CustomerSet: ")
816 .append(customerSet_ ? "true" : "false"));
817 auto dragPreviewStr =
818 std::string("DragPreview: Has customNode: ").append(dragPreviewInfo_.customNode ? "YES" : "NO");
819 dragPreviewStr.append(" Has pixelMap: ").append(dragPreviewInfo_.pixelMap ? "YES" : "NO");
820 dragPreviewStr.append(" extraInfo: ").append(dragPreviewInfo_.extraInfo.c_str());
821 dragPreviewStr.append(" inspectorId: ").append(dragPreviewInfo_.inspectorId.c_str());
822 DumpLog::GetInstance().AddDesc(dragPreviewStr);
823 auto eventHub = GetEventHub<EventHub>();
824 DumpLog::GetInstance().AddDesc(std::string("Event: ")
825 .append("OnDragStart: ")
826 .append(eventHub->HasOnDragStart() ? "YES" : "NO")
827 .append(" OnDragEnter: ")
828 .append(eventHub->HasOnDragEnter() ? "YES" : "NO")
829 .append(" OnDragLeave: ")
830 .append(eventHub->HasOnDragLeave() ? "YES" : "NO")
831 .append(" OnDragMove: ")
832 .append(eventHub->HasOnDragMove() ? "YES" : "NO")
833 .append(" OnDrop: ")
834 .append(eventHub->HasOnDrop() ? "YES" : "NO")
835 .append(" OnDragEnd: ")
836 .append(eventHub->HasOnDragEnd() ? "YES" : "NO"));
837 DumpLog::GetInstance().AddDesc(std::string("DefaultOnDragStart: ")
838 .append(eventHub->HasDefaultOnDragStart() ? "YES" : "NO")
839 .append(" CustomerOnDragEnter: ")
840 .append(eventHub->HasCustomerOnDragEnter() ? "YES" : "NO")
841 .append(" CustomerOnDragLeave: ")
842 .append(eventHub->HasCustomerOnDragLeave() ? "YES" : "NO")
843 .append(" CustomerOnDragMove: ")
844 .append(eventHub->HasCustomerOnDragMove() ? "YES" : "NO")
845 .append(" CustomerOnDrop: ")
846 .append(eventHub->HasCustomerOnDrop() ? "YES" : "NO")
847 .append(" CustomerOnDragEnd: ")
848 .append(eventHub->HasCustomerOnDragEnd() ? "YES" : "NO"));
849 DumpLog::GetInstance().AddDesc("------------end print dragInfo");
850 }
851
DumpOnSizeChangeInfo()852 void FrameNode::DumpOnSizeChangeInfo()
853 {
854 for (auto it = onSizeChangeDumpInfos.rbegin(); it != onSizeChangeDumpInfos.rend(); ++it) {
855 DumpLog::GetInstance().AddDesc(std::string("onSizeChange Time: ")
856 .append(ConvertTimestampToStr(it->onSizeChangeTimeStamp))
857 .append(" lastFrameRect: ")
858 .append(it->lastFrameRect.ToString())
859 .append(" currFrameRect: ")
860 .append(it->currFrameRect.ToString()));
861 }
862 }
863
DumpOverlayInfo()864 void FrameNode::DumpOverlayInfo()
865 {
866 if (!layoutProperty_->IsOverlayNode()) {
867 return;
868 }
869 DumpLog::GetInstance().AddDesc(std::string("IsOverlayNode: ").append(std::string("true")));
870 Dimension offsetX, offsetY;
871 layoutProperty_->GetOverlayOffset(offsetX, offsetY);
872 DumpLog::GetInstance().AddDesc(
873 std::string("OverlayOffset: ").append(offsetX.ToString()).append(std::string(", ")).append(offsetY.ToString()));
874 }
875
DumpSimplifyCommonInfo(std::unique_ptr<JsonValue> & json)876 void FrameNode::DumpSimplifyCommonInfo(std::unique_ptr<JsonValue>& json)
877 {
878 if (geometryNode_) {
879 if (geometryNode_->GetFrameRect() != RectF(0.0, 0.0, 0.0, 0.0)) {
880 json->Put("FrameRect", geometryNode_->GetFrameRect().ToString().c_str());
881 }
882 if (geometryNode_->GetParentLayoutConstraint().has_value()) {
883 json->Put("ParentLayoutConstraint", geometryNode_->GetParentLayoutConstraint().value().ToString().c_str());
884 }
885 auto offset = GetOffsetRelativeToWindow();
886 if (offset != OffsetF(0.0, 0.0)) {
887 std::stringstream stream;
888 stream << std::fixed << std::setprecision(DEFAULT_PRECISION) << offset.GetX() << "," << offset.GetY();
889 json->Put("Offset", stream.str().c_str());
890 }
891 }
892 if (renderContext_) {
893 if (renderContext_->GetPaintRectWithoutTransform() != RectF(0.0, 0.0, 0.0, 0.0)) {
894 json->Put("PaintRectWithoutTransform", renderContext_->GetPaintRectWithoutTransform().ToString().c_str());
895 }
896 if (renderContext_->GetBackgroundColor() &&
897 renderContext_->GetBackgroundColor()->ColorToString().compare("#00000000") != 0) {
898 json->Put("BackgroundColor", renderContext_->GetBackgroundColor()->ColorToString().c_str());
899 }
900 if (!NearZero(renderContext_->GetZIndexValue(ZINDEX_DEFAULT_VALUE))) {
901 json->Put("ZIndex: ", renderContext_->GetZIndexValue(ZINDEX_DEFAULT_VALUE));
902 }
903 }
904 if (layoutProperty_) {
905 VisibleType visible = layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE);
906 if (visible != VisibleType::VISIBLE) {
907 json->Put("Visible", static_cast<int32_t>(visible));
908 }
909 DumpPadding(layoutProperty_->GetPaddingProperty(), std::string("Padding"), json);
910 DumpBorder(layoutProperty_->GetBorderWidthProperty(), std::string("Border"), json);
911 DumpPadding(layoutProperty_->GetMarginProperty(), std::string("Margin"), json);
912 if (layoutProperty_->GetLayoutRect()) {
913 json->Put("LayoutRect", layoutProperty_->GetLayoutRect().value().ToString().c_str());
914 }
915 if (layoutProperty_->GetCalcLayoutConstraint()) {
916 json->Put("UserDefinedConstraint", layoutProperty_->GetCalcLayoutConstraint()->ToString().c_str());
917 }
918 if (layoutProperty_->GetPaddingProperty() || layoutProperty_->GetBorderWidthProperty() ||
919 layoutProperty_->GetMarginProperty() || layoutProperty_->GetCalcLayoutConstraint()) {
920 if (layoutProperty_->GetContentLayoutConstraint().has_value()) {
921 json->Put("ContentConstraint",
922 layoutProperty_->GetContentLayoutConstraint().value().ToString().c_str());
923 }
924 }
925 }
926 }
927
DumpPadding(const std::unique_ptr<NG::PaddingProperty> & padding,std::string label,std::unique_ptr<JsonValue> & json)928 void FrameNode::DumpPadding(const std::unique_ptr<NG::PaddingProperty>& padding, std::string label,
929 std::unique_ptr<JsonValue>& json)
930 {
931 CHECK_NULL_VOID(padding);
932 NG::CalcLength defaultValue = NG::CalcLength(
933 Dimension(0, padding->left.value_or(CalcLength()).GetDimension().Unit()));
934 if (padding->left.value_or(defaultValue) != defaultValue || padding->right.value_or(defaultValue) != defaultValue ||
935 padding->top.value_or(defaultValue) != defaultValue || padding->bottom.value_or(defaultValue) != defaultValue) {
936 json->Put(label.c_str(), padding->ToString().c_str());
937 }
938 }
939
DumpBorder(const std::unique_ptr<NG::BorderWidthProperty> & border,std::string label,std::unique_ptr<JsonValue> & json)940 void FrameNode::DumpBorder(const std::unique_ptr<NG::BorderWidthProperty>& border, std::string label,
941 std::unique_ptr<JsonValue>& json)
942 {
943 CHECK_NULL_VOID(border);
944 Dimension defaultValue(0, border->leftDimen.value_or(Dimension()).Unit());
945 if (border->leftDimen.value_or(defaultValue) != defaultValue ||
946 border->rightDimen.value_or(defaultValue) != defaultValue ||
947 border->topDimen.value_or(defaultValue) != defaultValue ||
948 border->bottomDimen.value_or(defaultValue) != defaultValue) {
949 json->Put(label.c_str(), border->ToString().c_str());
950 }
951 }
952
DumpSimplifySafeAreaInfo(std::unique_ptr<JsonValue> & json)953 void FrameNode::DumpSimplifySafeAreaInfo(std::unique_ptr<JsonValue>& json)
954 {
955 if (layoutProperty_) {
956 auto&& opts = layoutProperty_->GetSafeAreaExpandOpts();
957 if (opts && opts->type != NG::SAFE_AREA_TYPE_NONE && opts->edges != NG::SAFE_AREA_EDGE_NONE) {
958 json->Put("SafeAreaExpandOpts", opts->ToString().c_str());
959 }
960 if (layoutProperty_->GetSafeAreaInsets()) {
961 json->Put("SafeAreaInsets", layoutProperty_->GetSafeAreaInsets()->ToString().c_str());
962 }
963 }
964 if (SelfOrParentExpansive()) {
965 if (geometryNode_) {
966 RectF defaultValue(0.0, 0.0, 0.0, 0.0);
967 auto rect = geometryNode_->GetSelfAdjust();
968 auto parentRect = geometryNode_->GetParentAdjust();
969 if (rect != defaultValue) {
970 json->Put("SelfAdjust", rect.ToString().c_str());
971 }
972 if (parentRect != defaultValue) {
973 json->Put("ParentSelfAdjust", parentRect.ToString().c_str());
974 }
975 }
976 CHECK_EQUAL_VOID(GetTag(), V2::PAGE_ETS_TAG);
977 auto pipeline = GetContext();
978 CHECK_NULL_VOID(pipeline);
979 auto manager = pipeline->GetSafeAreaManager();
980 CHECK_NULL_VOID(manager);
981 if (!manager->IsIgnoreAsfeArea()) {
982 json->Put("IgnoreSafeArea", manager->IsIgnoreAsfeArea());
983 }
984 if (!manager->IsNeedAvoidWindow()) {
985 json->Put("IsNeedAvoidWindow", manager->IsNeedAvoidWindow());
986 }
987 if (!manager->IsFullScreen()) {
988 json->Put("IsFullScreen", manager->IsFullScreen());
989 }
990 if (!manager->KeyboardSafeAreaEnabled()) {
991 json->Put("IsKeyboardAvoidMode", manager->KeyboardSafeAreaEnabled());
992 }
993 if (!pipeline->GetUseCutout()) {
994 json->Put("IsUseCutout", pipeline->GetUseCutout());
995 }
996 }
997 }
998
DumpSimplifyOverlayInfo(std::unique_ptr<JsonValue> & json)999 void FrameNode::DumpSimplifyOverlayInfo(std::unique_ptr<JsonValue>& json)
1000 {
1001 if (layoutProperty_ || !layoutProperty_->IsOverlayNode()) {
1002 return;
1003 }
1004 json->Put("IsOverlayNode", true);
1005 Dimension offsetX;
1006 Dimension offsetY;
1007 layoutProperty_->GetOverlayOffset(offsetX, offsetY);
1008 json->Put("OverlayOffset", (offsetX.ToString() + "," + offsetY.ToString()).c_str());
1009 }
1010
DumpSimplifyInfo(std::unique_ptr<JsonValue> & json)1011 void FrameNode::DumpSimplifyInfo(std::unique_ptr<JsonValue>& json)
1012 {
1013 CHECK_NULL_VOID(json);
1014 DumpSimplifyCommonInfo(json);
1015 DumpSimplifySafeAreaInfo(json);
1016 DumpSimplifyOverlayInfo(json);
1017 if (renderContext_) {
1018 auto renderContextJson = JsonUtil::Create();
1019 renderContext_->DumpSimplifyInfo(renderContextJson);
1020 json->PutRef("RenderContext", std::move(renderContextJson));
1021 }
1022 }
1023
DumpInfo()1024 void FrameNode::DumpInfo()
1025 {
1026 DumpCommonInfo();
1027 DumpOnSizeChangeInfo();
1028 if (pattern_) {
1029 pattern_->DumpInfo();
1030 }
1031 if (renderContext_) {
1032 renderContext_->DumpInfo();
1033 }
1034 }
1035
DumpAdvanceInfo()1036 void FrameNode::DumpAdvanceInfo()
1037 {
1038 DumpCommonInfo();
1039 DumpOnSizeChangeInfo();
1040 if (pattern_) {
1041 pattern_->DumpInfo();
1042 pattern_->DumpAdvanceInfo();
1043 }
1044 if (renderContext_) {
1045 renderContext_->DumpInfo();
1046 renderContext_->DumpAdvanceInfo();
1047 }
1048 }
1049
DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap,bool needsRecordData)1050 void FrameNode::DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap, bool needsRecordData)
1051 {
1052 if (pattern_) {
1053 pattern_->DumpViewDataPageNode(viewDataWrap, needsRecordData);
1054 }
1055 }
1056
CheckAutoSave()1057 bool FrameNode::CheckAutoSave()
1058 {
1059 if (pattern_) {
1060 return pattern_->CheckAutoSave();
1061 }
1062 return false;
1063 }
1064
MouseToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1065 void FrameNode::MouseToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1066 {
1067 std::string hoverEffect = "HoverEffect.Auto";
1068 /* no fixed attr below, just return */
1069 if (filter.IsFastFilter()) {
1070 return;
1071 }
1072 auto inputEventHub = GetOrCreateInputEventHub();
1073 if (inputEventHub) {
1074 hoverEffect = inputEventHub->GetHoverEffectStr();
1075 }
1076 json->PutExtAttr("hoverEffect", hoverEffect.c_str(), filter);
1077 }
1078
TouchToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1079 void FrameNode::TouchToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1080 {
1081 bool touchable = true;
1082 bool monopolizeEvents = false;
1083 std::string hitTestMode = "HitTestMode.Default";
1084 /* no fixed attr below, just return */
1085 if (filter.IsFastFilter()) {
1086 return;
1087 }
1088 auto gestureEventHub = GetOrCreateGestureEventHub();
1089 std::vector<DimensionRect> responseRegion;
1090 std::vector<DimensionRect> mouseResponseRegion;
1091 if (gestureEventHub) {
1092 touchable = gestureEventHub->GetTouchable();
1093 hitTestMode = gestureEventHub->GetHitTestModeStr();
1094 responseRegion = gestureEventHub->GetResponseRegion();
1095 mouseResponseRegion = gestureEventHub->GetMouseResponseRegion();
1096 monopolizeEvents = gestureEventHub->GetMonopolizeEvents();
1097 }
1098 json->PutExtAttr("touchable", touchable, filter);
1099 json->PutExtAttr("hitTestBehavior", hitTestMode.c_str(), filter);
1100 json->PutExtAttr("monopolizeEvents", monopolizeEvents, filter);
1101 auto jsArr = JsonUtil::CreateArray(true);
1102 for (int32_t i = 0; i < static_cast<int32_t>(responseRegion.size()); ++i) {
1103 auto iStr = std::to_string(i);
1104 jsArr->Put(iStr.c_str(), responseRegion[i].ToJsonString().c_str());
1105 }
1106 json->PutExtAttr("responseRegion", jsArr, filter);
1107 for (int32_t i = 0; i < static_cast<int32_t>(mouseResponseRegion.size()); ++i) {
1108 auto iStr = std::to_string(i);
1109 jsArr->Put(iStr.c_str(), mouseResponseRegion[i].ToJsonString().c_str());
1110 }
1111 json->PutExtAttr("mouseResponseRegion", jsArr, filter);
1112 }
1113
GeometryNodeToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1114 void FrameNode::GeometryNodeToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1115 {
1116 bool hasIdealWidth = false;
1117 bool hasIdealHeight = false;
1118 /* no fixed attr below, just return */
1119 if (filter.IsFastFilter()) {
1120 return;
1121 }
1122 if (layoutProperty_ && layoutProperty_->GetCalcLayoutConstraint()) {
1123 auto selfIdealSize = layoutProperty_->GetCalcLayoutConstraint()->selfIdealSize;
1124 hasIdealWidth = selfIdealSize.has_value() && selfIdealSize.value().Width().has_value();
1125 hasIdealHeight = selfIdealSize.has_value() && selfIdealSize.value().Height().has_value();
1126 }
1127
1128 auto jsonSize = json->GetValue("size");
1129 if (!hasIdealWidth) {
1130 auto idealWidthVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Width()).ConvertToVp());
1131 auto widthStr = (idealWidthVpStr.substr(0, idealWidthVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP);
1132 json->PutExtAttr("width", widthStr.c_str(), filter);
1133 if (jsonSize) {
1134 jsonSize->Put("width", widthStr.c_str());
1135 }
1136 }
1137
1138 if (!hasIdealHeight) {
1139 auto idealHeightVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Height()).ConvertToVp());
1140 auto heightStr = (idealHeightVpStr.substr(0, idealHeightVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP);
1141 json->PutExtAttr("height", heightStr.c_str(), filter);
1142 if (jsonSize) {
1143 jsonSize->Put("height", heightStr.c_str());
1144 }
1145 }
1146 }
1147
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1148 void FrameNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1149 {
1150 if (renderContext_) {
1151 renderContext_->ToJsonValue(json, filter);
1152 }
1153 // scrollable in AccessibilityProperty
1154 ACE_PROPERTY_TO_JSON_VALUE(accessibilityProperty_, AccessibilityProperty);
1155 ACE_PROPERTY_TO_JSON_VALUE(layoutProperty_, LayoutProperty);
1156 ACE_PROPERTY_TO_JSON_VALUE(paintProperty_, PaintProperty);
1157 ACE_PROPERTY_TO_JSON_VALUE(pattern_, Pattern);
1158 if (eventHub_) {
1159 eventHub_->ToJsonValue(json, filter);
1160 }
1161 FocusHub::ToJsonValue(GetFocusHub(), json, filter);
1162 MouseToJsonValue(json, filter);
1163 TouchToJsonValue(json, filter);
1164 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1165 #if defined(PREVIEW)
1166 GeometryNodeToJsonValue(json, filter);
1167 #endif
1168 } else {
1169 GeometryNodeToJsonValue(json, filter);
1170 }
1171 json->PutFixedAttr("id", propInspectorId_.value_or("").c_str(), filter, FIXED_ATTR_ID);
1172 }
1173
FromJson(const std::unique_ptr<JsonValue> & json)1174 void FrameNode::FromJson(const std::unique_ptr<JsonValue>& json)
1175 {
1176 if (renderContext_) {
1177 renderContext_->FromJson(json);
1178 }
1179 accessibilityProperty_->FromJson(json);
1180 layoutProperty_->FromJson(json);
1181 paintProperty_->FromJson(json);
1182 pattern_->FromJson(json);
1183 if (eventHub_) {
1184 eventHub_->FromJson(json);
1185 }
1186 }
1187
UpdateGeometryTransition()1188 void FrameNode::UpdateGeometryTransition()
1189 {
1190 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
1191 if (geometryTransition) {
1192 layoutProperty_->UpdateGeometryTransition("");
1193 layoutProperty_->UpdateGeometryTransition(geometryTransition->GetId());
1194 MarkDirtyNode();
1195 }
1196 auto children = GetChildren();
1197 for (const auto& child : children) {
1198 child->UpdateGeometryTransition();
1199 }
1200 }
1201
OnAttachToMainTree(bool recursive)1202 void FrameNode::OnAttachToMainTree(bool recursive)
1203 {
1204 eventHub_->FireOnAttach();
1205 eventHub_->FireOnAppear();
1206 renderContext_->OnNodeAppear(recursive);
1207 pattern_->OnAttachToMainTree();
1208
1209 // node may have been measured before AttachToMainTree
1210 if (geometryNode_->GetParentLayoutConstraint().has_value() && !UseOffscreenProcess()) {
1211 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE_SELF);
1212 }
1213 UINode::OnAttachToMainTree(recursive);
1214 auto context = GetContext();
1215 CHECK_NULL_VOID(context);
1216 auto predictLayoutNode = std::move(predictLayoutNode_);
1217 for (auto& node : predictLayoutNode) {
1218 auto frameNode = node.Upgrade();
1219 if (frameNode && frameNode->isLayoutDirtyMarked_) {
1220 context->AddDirtyLayoutNode(frameNode);
1221 }
1222 }
1223
1224 if (isPropertyDiffMarked_) {
1225 context->AddDirtyPropertyNode(Claim(this));
1226 }
1227 if (!hasPendingRequest_) {
1228 return;
1229 }
1230 context->RequestFrame();
1231 hasPendingRequest_ = false;
1232 }
1233
OnAttachToBuilderNode(NodeStatus nodeStatus)1234 void FrameNode::OnAttachToBuilderNode(NodeStatus nodeStatus)
1235 {
1236 pattern_->OnAttachToBuilderNode(nodeStatus);
1237 }
1238
RenderCustomChild(int64_t deadline)1239 bool FrameNode::RenderCustomChild(int64_t deadline)
1240 {
1241 if (!pattern_->RenderCustomChild(deadline)) {
1242 return false;
1243 }
1244 return UINode::RenderCustomChild(deadline);
1245 }
1246
OnConfigurationUpdate(const ConfigurationChange & configurationChange)1247 void FrameNode::OnConfigurationUpdate(const ConfigurationChange& configurationChange)
1248 {
1249 if (configurationChange.languageUpdate) {
1250 pattern_->OnLanguageConfigurationUpdate();
1251 MarkModifyDone();
1252 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1253 }
1254 if (configurationChange.colorModeUpdate) {
1255 pattern_->OnColorConfigurationUpdate();
1256 if (colorModeUpdateCallback_) {
1257 // copy it first in case of changing colorModeUpdateCallback_ in the callback
1258 auto cb = colorModeUpdateCallback_;
1259 cb();
1260 }
1261 MarkModifyDone();
1262 MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1263 }
1264 if (configurationChange.directionUpdate) {
1265 pattern_->OnDirectionConfigurationUpdate();
1266 MarkModifyDone();
1267 MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1268 }
1269 if (configurationChange.dpiUpdate) {
1270 pattern_->OnDpiConfigurationUpdate();
1271 MarkModifyDone();
1272 MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1273 }
1274 if (configurationChange.fontUpdate) {
1275 pattern_->OnFontConfigurationUpdate();
1276 MarkModifyDone();
1277 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1278 }
1279 if (configurationChange.iconUpdate) {
1280 pattern_->OnIconConfigurationUpdate();
1281 MarkModifyDone();
1282 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1283 }
1284 if (configurationChange.skinUpdate) {
1285 MarkModifyDone();
1286 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1287 }
1288 if (configurationChange.fontScaleUpdate) {
1289 pattern_->OnFontScaleConfigurationUpdate();
1290 MarkModifyDone();
1291 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1292 }
1293 NotifyConfigurationChangeNdk(configurationChange);
1294 }
1295
NotifyConfigurationChangeNdk(const ConfigurationChange & configurationChange)1296 void FrameNode::NotifyConfigurationChangeNdk(const ConfigurationChange& configurationChange)
1297 {
1298 if (ndkColorModeUpdateCallback_ && configurationChange.colorModeUpdate &&
1299 colorMode_ != SystemProperties::GetColorMode()) {
1300 auto colorModeChange = ndkColorModeUpdateCallback_;
1301 colorModeChange(SystemProperties::GetColorMode() == ColorMode::DARK);
1302 colorMode_ = SystemProperties::GetColorMode();
1303 }
1304
1305 if (ndkFontUpdateCallback_ && (configurationChange.fontScaleUpdate || configurationChange.fontWeightScaleUpdate)) {
1306 auto fontChangeCallback = ndkFontUpdateCallback_;
1307 auto pipeline = GetContextWithCheck();
1308 CHECK_NULL_VOID(pipeline);
1309 fontChangeCallback(pipeline->GetFontScale(), pipeline->GetFontWeightScale());
1310 }
1311 }
1312
NotifyVisibleChange(VisibleType preVisibility,VisibleType currentVisibility)1313 void FrameNode::NotifyVisibleChange(VisibleType preVisibility, VisibleType currentVisibility)
1314 {
1315 if ((preVisibility != currentVisibility &&
1316 (preVisibility == VisibleType::GONE || currentVisibility == VisibleType::GONE)) &&
1317 SelfExpansive()) {
1318 MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1319 }
1320 pattern_->OnVisibleChange(currentVisibility == VisibleType::VISIBLE);
1321 UpdateChildrenVisible(preVisibility, currentVisibility);
1322 }
1323
TryVisibleChangeOnDescendant(VisibleType preVisibility,VisibleType currentVisibility)1324 void FrameNode::TryVisibleChangeOnDescendant(VisibleType preVisibility, VisibleType currentVisibility)
1325 {
1326 auto layoutProperty = GetLayoutProperty();
1327 if (layoutProperty && layoutProperty->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE) {
1328 return;
1329 }
1330 NotifyVisibleChange(preVisibility, currentVisibility);
1331 }
1332
OnDetachFromMainTree(bool recursive,PipelineContext * context)1333 void FrameNode::OnDetachFromMainTree(bool recursive, PipelineContext* context)
1334 {
1335 auto focusHub = GetFocusHub();
1336 if (focusHub) {
1337 auto focusView = focusHub->GetFirstChildFocusView();
1338 if (focusView) {
1339 focusView->FocusViewClose();
1340 }
1341 focusHub->RemoveSelf();
1342 }
1343 eventHub_->FireOnDetach();
1344 pattern_->OnDetachFromMainTree();
1345 eventHub_->FireOnDisappear();
1346 CHECK_NULL_VOID(renderContext_);
1347 renderContext_->OnNodeDisappear(recursive);
1348 if (context) {
1349 const auto& safeAreaManager = context->GetSafeAreaManager();
1350 if (safeAreaManager) {
1351 safeAreaManager->RemoveRestoreNode(WeakClaim(this));
1352 }
1353 }
1354 }
1355
SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper> & dirty)1356 void FrameNode::SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper>& dirty)
1357 {
1358 CHECK_NULL_VOID(dirty);
1359
1360 // update new layout constrain.
1361 layoutProperty_->UpdateLayoutConstraint(dirty->GetLayoutProperty());
1362
1363 // active change flag judge.
1364 SetActive(dirty->IsActive());
1365 if (!isActive_) {
1366 return;
1367 }
1368
1369 // update layout size.
1370 bool frameSizeChange = geometryNode_->GetFrameSize() != dirty->GetGeometryNode()->GetFrameSize();
1371 bool frameOffsetChange = geometryNode_->GetFrameOffset() != dirty->GetGeometryNode()->GetFrameOffset();
1372 bool contentSizeChange = geometryNode_->GetContentSize() != dirty->GetGeometryNode()->GetContentSize();
1373 bool contentOffsetChange = geometryNode_->GetContentOffset() != dirty->GetGeometryNode()->GetContentOffset();
1374
1375 SetGeometryNode(dirty->GetGeometryNode());
1376
1377 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
1378 if (geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this))) {
1379 geometryTransition->DidLayout(dirty);
1380 if (geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
1381 isLayoutDirtyMarked_ = true;
1382 }
1383 } else if (frameSizeChange || frameOffsetChange || HasPositionProp() ||
1384 (pattern_->GetContextParam().has_value() && contentSizeChange)) {
1385 renderContext_->SyncGeometryProperties(RawPtr(dirty->GetGeometryNode()));
1386 }
1387
1388 // clean layout flag.
1389 layoutProperty_->CleanDirty();
1390 DirtySwapConfig config { frameSizeChange, frameOffsetChange, contentSizeChange, contentOffsetChange };
1391 // check if need to paint content.
1392 auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
1393 CHECK_NULL_VOID(layoutAlgorithmWrapper);
1394 config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure() || dirty->SkipMeasureContent();
1395 config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
1396 if ((config.skipMeasure == false) && (config.skipLayout == false) && GetInspectorId().has_value()) {
1397 auto pipeline = GetContext();
1398 CHECK_NULL_VOID(pipeline);
1399 pipeline->OnLayoutCompleted(GetInspectorId()->c_str());
1400 }
1401 auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(dirty, config);
1402 needRerender = needRerender || pattern_->OnDirtyLayoutWrapperSwap(dirty, config.skipMeasure, config.skipLayout);
1403 if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
1404 MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
1405 }
1406
1407 // update border.
1408 if (layoutProperty_->GetBorderWidthProperty()) {
1409 if (!renderContext_->HasBorderColor()) {
1410 BorderColorProperty borderColorProperty;
1411 borderColorProperty.SetColor(Color::BLACK);
1412 renderContext_->UpdateBorderColor(borderColorProperty);
1413 }
1414 if (!renderContext_->HasBorderStyle()) {
1415 BorderStyleProperty borderStyleProperty;
1416 borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
1417 renderContext_->UpdateBorderStyle(borderStyleProperty);
1418 }
1419 if (!renderContext_->HasDashGap()) {
1420 BorderWidthProperty dashGapProperty;
1421 dashGapProperty.SetBorderWidth(Dimension(-1));
1422 renderContext_->UpdateDashGap(dashGapProperty);
1423 }
1424 if (!renderContext_->HasDashWidth()) {
1425 BorderWidthProperty dashWidthProperty;
1426 dashWidthProperty.SetBorderWidth(Dimension(-1));
1427 renderContext_->UpdateDashWidth(dashWidthProperty);
1428 }
1429 if (layoutProperty_->GetLayoutConstraint().has_value()) {
1430 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
1431 ScaleProperty::CreateScaleProperty(),
1432 layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
1433 } else {
1434 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
1435 ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
1436 }
1437 }
1438
1439 // update background
1440 if (builderFunc_) {
1441 auto builderNode = builderFunc_();
1442 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1443 AceType::MakeRefPtr<LinearLayoutPattern>(true));
1444 if (builderNode) {
1445 builderNode->MountToParent(columnNode);
1446 }
1447 SetBackgroundLayoutConstraint(columnNode);
1448 renderContext_->CreateBackgroundPixelMap(columnNode);
1449 builderFunc_ = nullptr;
1450 backgroundNode_ = columnNode;
1451 }
1452 UpdateFocusState();
1453
1454 // rebuild child render node.
1455 RebuildRenderContextTree();
1456 }
1457
SetBackgroundLayoutConstraint(const RefPtr<FrameNode> & customNode)1458 void FrameNode::SetBackgroundLayoutConstraint(const RefPtr<FrameNode>& customNode)
1459 {
1460 CHECK_NULL_VOID(customNode);
1461 LayoutConstraintF layoutConstraint;
1462 layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
1463 layoutConstraint.percentReference.SetWidth(geometryNode_->GetFrameSize().Width());
1464 layoutConstraint.percentReference.SetHeight(geometryNode_->GetFrameSize().Height());
1465 layoutConstraint.maxSize.SetWidth(geometryNode_->GetFrameSize().Width());
1466 layoutConstraint.maxSize.SetHeight(geometryNode_->GetFrameSize().Height());
1467 customNode->GetGeometryNode()->SetParentLayoutConstraint(layoutConstraint);
1468 }
1469
AdjustGridOffset()1470 void FrameNode::AdjustGridOffset()
1471 {
1472 if (!isActive_) {
1473 return;
1474 }
1475 if (layoutProperty_->UpdateGridOffset(Claim(this))) {
1476 renderContext_->UpdateOffset(OffsetT<Dimension>());
1477 renderContext_->UpdateAnchor(OffsetT<Dimension>());
1478 renderContext_->SyncGeometryProperties(RawPtr(GetGeometryNode()));
1479 }
1480 }
1481
ClearUserOnAreaChange()1482 void FrameNode::ClearUserOnAreaChange()
1483 {
1484 if (eventHub_) {
1485 eventHub_->ClearUserOnAreaChanged();
1486 }
1487 }
1488
SetOnAreaChangeCallback(OnAreaChangedFunc && callback)1489 void FrameNode::SetOnAreaChangeCallback(OnAreaChangedFunc&& callback)
1490 {
1491 InitLastArea();
1492 eventHub_->SetOnAreaChanged(std::move(callback));
1493 }
1494
TriggerOnAreaChangeCallback(uint64_t nanoTimestamp)1495 void FrameNode::TriggerOnAreaChangeCallback(uint64_t nanoTimestamp)
1496 {
1497 if (!IsActive()) {
1498 return;
1499 }
1500 if ((eventHub_->HasOnAreaChanged() || eventHub_->HasInnerOnAreaChanged()) && lastFrameRect_ &&
1501 lastParentOffsetToWindow_) {
1502 auto currFrameRect = geometryNode_->GetFrameRect();
1503 if (renderContext_ && renderContext_->GetPositionProperty()) {
1504 if (renderContext_->GetPositionProperty()->HasPosition()) {
1505 auto renderPosition = ContextPositionConvertToPX(
1506 renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
1507 currFrameRect.SetOffset(
1508 { static_cast<float>(renderPosition.first), static_cast<float>(renderPosition.second) });
1509 }
1510 }
1511 auto currParentOffsetToWindow = CalculateOffsetRelativeToWindow(nanoTimestamp) - currFrameRect.GetOffset();
1512 if (currFrameRect != *lastFrameRect_ || currParentOffsetToWindow != *lastParentOffsetToWindow_) {
1513 if (eventHub_->HasInnerOnAreaChanged()) {
1514 eventHub_->FireInnerOnAreaChanged(
1515 *lastFrameRect_, *lastParentOffsetToWindow_, currFrameRect, currParentOffsetToWindow);
1516 }
1517 if (eventHub_->HasOnAreaChanged()) {
1518 eventHub_->FireOnAreaChanged(*lastFrameRect_, *lastParentOffsetToWindow_,
1519 GetFrameRectWithSafeArea(true), GetParentGlobalOffsetWithSafeArea(true, true));
1520 }
1521 *lastFrameRect_ = currFrameRect;
1522 *lastParentOffsetToWindow_ = currParentOffsetToWindow;
1523 }
1524 }
1525 pattern_->OnAreaChangedInner();
1526 }
1527
SetOnSizeChangeCallback(OnSizeChangedFunc && callback)1528 void FrameNode::SetOnSizeChangeCallback(OnSizeChangedFunc&& callback)
1529 {
1530 if (!lastFrameNodeRect_) {
1531 lastFrameNodeRect_ = std::make_unique<RectF>();
1532 }
1533 eventHub_->SetOnSizeChanged(std::move(callback));
1534 }
1535
AddInnerOnSizeChangeCallback(int32_t id,OnSizeChangedFunc && callback)1536 void FrameNode::AddInnerOnSizeChangeCallback(int32_t id, OnSizeChangedFunc&& callback)
1537 {
1538 if (!lastFrameNodeRect_) {
1539 lastFrameNodeRect_ = std::make_unique<RectF>();
1540 }
1541 eventHub_->AddInnerOnSizeChanged(id, std::move(callback));
1542 }
1543
SetJSFrameNodeOnSizeChangeCallback(OnSizeChangedFunc && callback)1544 void FrameNode::SetJSFrameNodeOnSizeChangeCallback(OnSizeChangedFunc&& callback)
1545 {
1546 if (!lastFrameNodeRect_) {
1547 lastFrameNodeRect_ = std::make_unique<RectF>();
1548 }
1549 eventHub_->SetJSFrameNodeOnSizeChangeCallback(std::move(callback));
1550 }
1551
GetRectWithFrame()1552 RectF FrameNode::GetRectWithFrame()
1553 {
1554 auto currFrameRect = geometryNode_->GetFrameRect();
1555 if (renderContext_ && renderContext_->GetPositionProperty()) {
1556 if (renderContext_->GetPositionProperty()->HasPosition()) {
1557 auto renderPosition = ContextPositionConvertToPX(
1558 renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
1559 currFrameRect.SetOffset(
1560 { static_cast<float>(renderPosition.first), static_cast<float>(renderPosition.second) });
1561 }
1562 }
1563 return currFrameRect;
1564 }
1565
GetRectWithRender()1566 RectF FrameNode::GetRectWithRender()
1567 {
1568 RectF currFrameRect;
1569 if (renderContext_) {
1570 currFrameRect = renderContext_->GetPaintRectWithoutTransform();
1571 }
1572 if (renderContext_ && renderContext_->GetPositionProperty()) {
1573 if (renderContext_->GetPositionProperty()->HasPosition()) {
1574 auto renderPosition =
1575 ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
1576 currFrameRect.SetOffset(
1577 { static_cast<float>(renderPosition.first), static_cast<float>(renderPosition.second) });
1578 }
1579 }
1580 return currFrameRect;
1581 }
1582
CheckAncestorPageShow()1583 bool FrameNode::CheckAncestorPageShow()
1584 {
1585 auto pageNode = GetPageNode();
1586 if (!pageNode) {
1587 return true;
1588 }
1589 return pageNode->GetPattern<PagePattern>()->IsOnShow();
1590 }
1591
TriggerOnSizeChangeCallback()1592 void FrameNode::TriggerOnSizeChangeCallback()
1593 {
1594 if (!IsActive() || !CheckAncestorPageShow()) {
1595 return;
1596 }
1597 if ((eventHub_->HasOnSizeChanged() || eventHub_->HasInnerOnSizeChanged()) && lastFrameNodeRect_) {
1598 auto currFrameRect = GetRectWithRender();
1599 if (currFrameRect.GetSize() != (*lastFrameNodeRect_).GetSize()) {
1600 onSizeChangeDumpInfo dumpInfo { GetCurrentTimestamp(), *lastFrameNodeRect_, currFrameRect };
1601 if (onSizeChangeDumpInfos.size() >= SIZE_CHANGE_DUMP_SIZE) {
1602 onSizeChangeDumpInfos.erase(onSizeChangeDumpInfos.begin());
1603 }
1604 onSizeChangeDumpInfos.emplace_back(dumpInfo);
1605 if (eventHub_->HasOnSizeChanged()) {
1606 eventHub_->FireOnSizeChanged(*lastFrameNodeRect_, currFrameRect);
1607 }
1608 if (eventHub_->HasInnerOnSizeChanged()) {
1609 eventHub_->FireInnerOnSizeChanged(*lastFrameNodeRect_, currFrameRect);
1610 }
1611 eventHub_->FireJSFrameNodeOnSizeChanged(*lastFrameNodeRect_, currFrameRect);
1612 *lastFrameNodeRect_ = currFrameRect;
1613 }
1614 }
1615 }
1616
IsFrameDisappear()1617 bool FrameNode::IsFrameDisappear()
1618 {
1619 auto context = GetContext();
1620 CHECK_NULL_RETURN(context, true);
1621 bool isFrameDisappear = !context->GetOnShow() || !IsOnMainTree() || !IsVisible();
1622 if (isFrameDisappear) {
1623 return true;
1624 }
1625 bool curFrameIsActive = isActive_;
1626 bool curIsVisible = IsVisible();
1627 auto parent = GetParent();
1628 while (parent) {
1629 auto parentFrame = AceType::DynamicCast<FrameNode>(parent);
1630 if (!parentFrame) {
1631 parent = parent->GetParent();
1632 continue;
1633 }
1634 if (!parentFrame->isActive_) {
1635 curFrameIsActive = false;
1636 break;
1637 }
1638 if (!parentFrame->IsVisible()) {
1639 curIsVisible = false;
1640 break;
1641 }
1642 parent = parent->GetParent();
1643 }
1644 return !curIsVisible || !curFrameIsActive;
1645 }
1646
IsFrameDisappear(uint64_t timestamp)1647 bool FrameNode::IsFrameDisappear(uint64_t timestamp)
1648 {
1649 auto context = GetContext();
1650 CHECK_NULL_RETURN(context, true);
1651 bool isFrameDisappear = !context->GetOnShow() || !AllowVisibleAreaCheck() || !IsVisible();
1652 if (isFrameDisappear) {
1653 cachedIsFrameDisappear_ = { timestamp, true };
1654 return true;
1655 }
1656
1657 return IsFrameAncestorDisappear(timestamp);
1658 }
1659
IsFrameAncestorDisappear(uint64_t timestamp)1660 bool FrameNode::IsFrameAncestorDisappear(uint64_t timestamp)
1661 {
1662 bool curFrameIsActive = isActive_;
1663 bool curIsVisible = IsVisible();
1664 bool result = !curIsVisible || !curFrameIsActive;
1665 RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame();
1666 if (!parentUi) {
1667 cachedIsFrameDisappear_ = { timestamp, result };
1668 return result;
1669 }
1670
1671 auto parentIsFrameDisappear = parentUi->cachedIsFrameDisappear_;
1672 if (parentIsFrameDisappear.first == timestamp) {
1673 result = result || parentIsFrameDisappear.second;
1674 cachedIsFrameDisappear_ = { timestamp, result };
1675 return result;
1676 }
1677 result = result || (parentUi->IsFrameAncestorDisappear(timestamp));
1678 cachedIsFrameDisappear_ = { timestamp, result };
1679 return result;
1680 }
1681
TriggerVisibleAreaChangeCallback(uint64_t timestamp,bool forceDisappear)1682 void FrameNode::TriggerVisibleAreaChangeCallback(uint64_t timestamp, bool forceDisappear)
1683 {
1684 auto context = GetContext();
1685 CHECK_NULL_VOID(context);
1686 CHECK_NULL_VOID(eventHub_);
1687
1688 ProcessThrottledVisibleCallback();
1689 auto hasInnerCallback = eventHub_->HasVisibleAreaCallback(false);
1690 auto hasUserCallback = eventHub_->HasVisibleAreaCallback(true);
1691 if (!hasInnerCallback && !hasUserCallback) {
1692 return;
1693 }
1694
1695 auto& visibleAreaUserRatios = eventHub_->GetVisibleAreaRatios(true);
1696 auto& visibleAreaUserCallback = eventHub_->GetVisibleAreaCallback(true);
1697 auto& visibleAreaInnerRatios = eventHub_->GetVisibleAreaRatios(false);
1698 auto& visibleAreaInnerCallback = eventHub_->GetVisibleAreaCallback(false);
1699
1700 if (forceDisappear || IsFrameDisappear(timestamp)) {
1701 if (!NearEqual(lastInnerVisibleRatio_, VISIBLE_RATIO_MIN)) {
1702 ProcessAllVisibleCallback(visibleAreaInnerRatios, visibleAreaInnerCallback, VISIBLE_RATIO_MIN,
1703 lastInnerVisibleCallbackRatio_, false, true);
1704 lastInnerVisibleRatio_ = VISIBLE_RATIO_MIN;
1705 }
1706 if (!NearEqual(lastVisibleRatio_, VISIBLE_RATIO_MIN)) {
1707 ProcessAllVisibleCallback(
1708 visibleAreaUserRatios, visibleAreaUserCallback, VISIBLE_RATIO_MIN, lastVisibleCallbackRatio_);
1709 lastVisibleRatio_ = VISIBLE_RATIO_MIN;
1710 }
1711 return;
1712 }
1713
1714 if (hasInnerCallback) {
1715 auto visibleResult = GetCacheVisibleRect(timestamp);
1716 if (isCalculateInnerVisibleRectClip_) {
1717 ProcessVisibleAreaChangeEvent(visibleResult.innerVisibleRect, visibleResult.frameRect,
1718 visibleAreaInnerRatios, visibleAreaInnerCallback, false);
1719 } else {
1720 ProcessVisibleAreaChangeEvent(visibleResult.visibleRect, visibleResult.frameRect,
1721 visibleAreaInnerRatios, visibleAreaInnerCallback, false);
1722 }
1723 if (hasUserCallback) {
1724 ProcessVisibleAreaChangeEvent(visibleResult.visibleRect, visibleResult.frameRect,
1725 visibleAreaUserRatios, visibleAreaUserCallback, true);
1726 }
1727 } else {
1728 auto visibleResult = GetCacheVisibleRect(timestamp);
1729 ProcessVisibleAreaChangeEvent(visibleResult.visibleRect, visibleResult.frameRect,
1730 visibleAreaUserRatios, visibleAreaUserCallback, true);
1731 }
1732 }
1733
ProcessVisibleAreaChangeEvent(const RectF & visibleRect,const RectF & frameRect,const std::vector<double> & visibleAreaRatios,VisibleCallbackInfo & visibleAreaCallback,bool isUser)1734 void FrameNode::ProcessVisibleAreaChangeEvent(const RectF& visibleRect, const RectF& frameRect,
1735 const std::vector<double>& visibleAreaRatios, VisibleCallbackInfo& visibleAreaCallback, bool isUser)
1736 {
1737 double currentVisibleRatio =
1738 std::clamp(CalculateCurrentVisibleRatio(visibleRect, frameRect), VISIBLE_RATIO_MIN, VISIBLE_RATIO_MAX);
1739 if (isUser) {
1740 if (!NearEqual(currentVisibleRatio, lastVisibleRatio_)) {
1741 auto lastVisibleCallbackRatio = lastVisibleCallbackRatio_;
1742 ProcessAllVisibleCallback(
1743 visibleAreaRatios, visibleAreaCallback, currentVisibleRatio, lastVisibleCallbackRatio);
1744 lastVisibleRatio_ = currentVisibleRatio;
1745 }
1746 } else {
1747 if (!NearEqual(currentVisibleRatio, lastInnerVisibleRatio_)) {
1748 auto lastVisibleCallbackRatio = lastInnerVisibleCallbackRatio_;
1749 ProcessAllVisibleCallback(visibleAreaRatios, visibleAreaCallback, currentVisibleRatio,
1750 lastVisibleCallbackRatio, false, true);
1751 lastInnerVisibleRatio_ = currentVisibleRatio;
1752 }
1753 }
1754 }
1755
CalculateCurrentVisibleRatio(const RectF & visibleRect,const RectF & renderRect)1756 double FrameNode::CalculateCurrentVisibleRatio(const RectF& visibleRect, const RectF& renderRect)
1757 {
1758 if (visibleRect.IsEmpty() || renderRect.IsEmpty()) {
1759 return 0.0;
1760 }
1761 return visibleRect.Width() * visibleRect.Height() / (renderRect.Width() * renderRect.Height());
1762 }
1763
ProcessAllVisibleCallback(const std::vector<double> & visibleAreaUserRatios,VisibleCallbackInfo & visibleAreaUserCallback,double currentVisibleRatio,double lastVisibleRatio,bool isThrottled,bool isInner)1764 void FrameNode::ProcessAllVisibleCallback(const std::vector<double>& visibleAreaUserRatios,
1765 VisibleCallbackInfo& visibleAreaUserCallback, double currentVisibleRatio, double lastVisibleRatio,
1766 bool isThrottled, bool isInner)
1767 {
1768 bool isHandled = false;
1769 bool isVisible = false;
1770 double* lastVisibleCallbackRatio = isThrottled ? &lastThrottledVisibleCbRatio_ :
1771 (isInner ? &lastInnerVisibleCallbackRatio_ : &lastVisibleCallbackRatio_);
1772
1773 for (const auto& callbackRatio : visibleAreaUserRatios) {
1774 if (GreatNotEqual(currentVisibleRatio, callbackRatio) && LessOrEqual(lastVisibleRatio, callbackRatio)) {
1775 *lastVisibleCallbackRatio = currentVisibleRatio;
1776 isVisible = true;
1777 isHandled = true;
1778 } else if (LessNotEqual(currentVisibleRatio, callbackRatio) && GreatOrEqual(lastVisibleRatio, callbackRatio)) {
1779 *lastVisibleCallbackRatio = currentVisibleRatio;
1780 isVisible = false;
1781 isHandled = true;
1782 } else if (NearEqual(callbackRatio, VISIBLE_RATIO_MIN) && NearEqual(currentVisibleRatio, callbackRatio)) {
1783 *lastVisibleCallbackRatio = VISIBLE_RATIO_MIN;
1784 currentVisibleRatio = VISIBLE_RATIO_MIN;
1785 isVisible = false;
1786 isHandled = true;
1787 } else if (NearEqual(callbackRatio, VISIBLE_RATIO_MAX) && NearEqual(currentVisibleRatio, callbackRatio)) {
1788 *lastVisibleCallbackRatio = VISIBLE_RATIO_MAX;
1789 currentVisibleRatio = VISIBLE_RATIO_MAX;
1790 isVisible = true;
1791 isHandled = true;
1792 }
1793 }
1794
1795 auto callback = visibleAreaUserCallback.callback;
1796 if (isHandled && callback) {
1797 callback(isVisible, currentVisibleRatio);
1798 }
1799 }
1800
ThrottledVisibleTask()1801 void FrameNode::ThrottledVisibleTask()
1802 {
1803 CHECK_NULL_VOID(eventHub_);
1804 auto& userRatios = eventHub_->GetThrottledVisibleAreaRatios();
1805 auto& userCallback = eventHub_->GetThrottledVisibleAreaCallback();
1806 CHECK_NULL_VOID(userCallback.callback);
1807 if (!throttledCallbackOnTheWay_) {
1808 return;
1809 }
1810
1811 auto pipeline = GetContext();
1812 CHECK_NULL_VOID(pipeline);
1813 auto visibleAreaRealTime = pipeline->GetVisibleAreaRealTime();
1814 auto visibleResult = GetCacheVisibleRect(pipeline->GetVsyncTime());
1815 RectF frameRect = visibleResult.frameRect;
1816 RectF visibleRect = visibleResult.visibleRect;
1817 double ratio = IsFrameDisappear() ? VISIBLE_RATIO_MIN
1818 : std::clamp(CalculateCurrentVisibleRatio(visibleRect, frameRect),
1819 VISIBLE_RATIO_MIN, VISIBLE_RATIO_MAX);
1820 if (visibleAreaRealTime) {
1821 if (NearEqual(ratio, lastThrottledVisibleRatio_)) {
1822 throttledCallbackOnTheWay_ = false;
1823 return;
1824 }
1825 ProcessAllVisibleCallback(userRatios, userCallback, ratio, lastThrottledVisibleCbRatio_, true);
1826 lastThrottledVisibleRatio_ = ratio;
1827 throttledCallbackOnTheWay_ = false;
1828 lastThrottledTriggerTime_ = GetCurrentTimestamp();
1829 } else {
1830 if (!NearEqual(ratio, lastThrottledVisibleRatio_)) {
1831 ProcessAllVisibleCallback(userRatios, userCallback, ratio, lastThrottledVisibleCbRatio_, true);
1832 lastThrottledVisibleRatio_ = ratio;
1833 }
1834 throttledCallbackOnTheWay_ = false;
1835 lastThrottledTriggerTime_ = GetCurrentTimestamp();
1836 }
1837 }
1838
ProcessThrottledVisibleCallback()1839 void FrameNode::ProcessThrottledVisibleCallback()
1840 {
1841 CHECK_NULL_VOID(eventHub_);
1842 auto& visibleAreaUserCallback = eventHub_->GetThrottledVisibleAreaCallback();
1843 CHECK_NULL_VOID(visibleAreaUserCallback.callback);
1844
1845 auto task = [weak = WeakClaim(this)]() {
1846 auto node = weak.Upgrade();
1847 CHECK_NULL_VOID(node);
1848 node->ThrottledVisibleTask();
1849 };
1850
1851 auto pipeline = GetContextRefPtr();
1852 CHECK_NULL_VOID(pipeline);
1853 auto executor = pipeline->GetTaskExecutor();
1854 CHECK_NULL_VOID(executor);
1855
1856 if (throttledCallbackOnTheWay_) {
1857 return;
1858 }
1859
1860 throttledCallbackOnTheWay_ = true;
1861 int64_t interval = GetCurrentTimestamp() - lastThrottledTriggerTime_;
1862 if (interval < visibleAreaUserCallback.period) {
1863 executor->PostDelayedTask(std::move(task), TaskExecutor::TaskType::UI, visibleAreaUserCallback.period,
1864 "ThrottledVisibleChangeCallback", PriorityType::IDLE);
1865 } else {
1866 executor->PostTask(
1867 std::move(task), TaskExecutor::TaskType::UI, "ThrottledVisibleChangeCallback", PriorityType::IDLE);
1868 }
1869 }
1870
SetActive(bool active,bool needRebuildRenderContext)1871 void FrameNode::SetActive(bool active, bool needRebuildRenderContext)
1872 {
1873 bool activeChanged = false;
1874 if (active && !isActive_) {
1875 pattern_->OnActive();
1876 isActive_ = true;
1877 activeChanged = true;
1878 }
1879 if (!active && isActive_) {
1880 pattern_->OnInActive();
1881 isActive_ = false;
1882 activeChanged = true;
1883 }
1884 CHECK_NULL_VOID(activeChanged);
1885 auto parent = GetAncestorNodeOfFrame();
1886 if (parent) {
1887 parent->MarkNeedSyncRenderTree();
1888 if (needRebuildRenderContext) {
1889 auto pipeline = GetContext();
1890 CHECK_NULL_VOID(pipeline);
1891 auto task = [weak = AceType::WeakClaim(AceType::RawPtr(parent))]() {
1892 auto parent = weak.Upgrade();
1893 CHECK_NULL_VOID(parent);
1894 parent->RebuildRenderContextTree();
1895 };
1896 pipeline->AddAfterLayoutTask(task);
1897 }
1898 }
1899 if (isActive_ && SystemProperties::GetDeveloperModeOn()) {
1900 PaintDebugBoundary(SystemProperties::GetDebugBoundaryEnabled());
1901 }
1902 }
1903
SetGeometryNode(const RefPtr<GeometryNode> & node)1904 void FrameNode::SetGeometryNode(const RefPtr<GeometryNode>& node)
1905 {
1906 geometryNode_ = node;
1907 }
1908
CreateLayoutTask(bool forceUseMainThread)1909 void FrameNode::CreateLayoutTask(bool forceUseMainThread)
1910 {
1911 if (!isLayoutDirtyMarked_) {
1912 return;
1913 }
1914 SetRootMeasureNode(true);
1915 UpdateLayoutPropertyFlag();
1916 SetSkipSyncGeometryNode(false);
1917 if (layoutProperty_->GetLayoutRect()) {
1918 SetActive(true, true);
1919 Measure(std::nullopt);
1920 Layout();
1921 } else {
1922 {
1923 auto layoutConstraint = GetLayoutConstraint();
1924 ACE_SCOPED_TRACE("CreateTaskMeasure[%s][self:%d][parent:%d][layoutConstraint:%s]", GetTag().c_str(),
1925 GetId(), GetAncestorNodeOfFrame() ? GetAncestorNodeOfFrame()->GetId() : 0,
1926 layoutConstraint.ToString().c_str());
1927 Measure(layoutConstraint);
1928 }
1929 {
1930 ACE_SCOPED_TRACE("CreateTaskLayout[%s][self:%d][parent:%d]", GetTag().c_str(), GetId(),
1931 GetAncestorNodeOfFrame() ? GetAncestorNodeOfFrame()->GetId() : 0);
1932 Layout();
1933 }
1934 }
1935 SetRootMeasureNode(false);
1936 }
1937
CreateRenderTask(bool forceUseMainThread)1938 std::optional<UITask> FrameNode::CreateRenderTask(bool forceUseMainThread)
1939 {
1940 if (!isRenderDirtyMarked_) {
1941 return std::nullopt;
1942 }
1943 auto wrapper = CreatePaintWrapper();
1944 CHECK_NULL_RETURN(wrapper, std::nullopt);
1945 auto task = [weak = WeakClaim(this), wrapper, paintProperty = paintProperty_]() {
1946 auto self = weak.Upgrade();
1947 ACE_SCOPED_TRACE("FrameNode[%s][id:%d]::RenderTask", self->GetTag().c_str(), self->GetId());
1948 ArkUIPerfMonitor::GetInstance().RecordRenderNode();
1949 wrapper->FlushRender();
1950 paintProperty->CleanDirty();
1951
1952 if (self->GetInspectorId()) {
1953 auto pipeline = PipelineContext::GetCurrentContext();
1954 CHECK_NULL_VOID(pipeline);
1955 pipeline->SetNeedRenderNode(weak);
1956 }
1957 };
1958 if (forceUseMainThread || wrapper->CheckShouldRunOnMain()) {
1959 return UITask(std::move(task), MAIN_TASK);
1960 }
1961 return UITask(std::move(task), wrapper->CanRunOnWhichThread());
1962 }
1963
GetLayoutConstraint() const1964 LayoutConstraintF FrameNode::GetLayoutConstraint() const
1965 {
1966 if (geometryNode_->GetParentLayoutConstraint().has_value()) {
1967 return geometryNode_->GetParentLayoutConstraint().value();
1968 }
1969 LayoutConstraintF layoutConstraint;
1970 layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
1971 auto rootWidth = PipelineContext::GetCurrentRootWidth();
1972 auto rootHeight = PipelineContext::GetCurrentRootHeight();
1973 layoutConstraint.percentReference.SetWidth(rootWidth);
1974 layoutConstraint.percentReference.SetHeight(rootHeight);
1975 layoutConstraint.maxSize.SetWidth(rootWidth);
1976 layoutConstraint.maxSize.SetHeight(rootHeight);
1977 return layoutConstraint;
1978 }
1979
GetParentGlobalOffset() const1980 OffsetF FrameNode::GetParentGlobalOffset() const
1981 {
1982 auto parent = GetAncestorNodeOfFrame();
1983 if (!parent) {
1984 return { 0.0f, 0.0f };
1985 }
1986 return parent->geometryNode_->GetParentGlobalOffset();
1987 }
1988
UpdateLayoutPropertyFlag()1989 void FrameNode::UpdateLayoutPropertyFlag()
1990 {
1991 auto selfFlag = layoutProperty_->GetPropertyChangeFlag();
1992 if (!CheckUpdateByChildRequest(selfFlag)) {
1993 return;
1994 }
1995 if (CheckForceParentMeasureFlag(selfFlag)) {
1996 return;
1997 }
1998 auto flag = PROPERTY_UPDATE_NORMAL;
1999 const auto& children = GetChildren();
2000 for (const auto& child : children) {
2001 child->UpdateLayoutPropertyFlag();
2002 child->AdjustParentLayoutFlag(flag);
2003 if (CheckForceParentMeasureFlag(selfFlag)) {
2004 break;
2005 }
2006 }
2007 if (CheckForceParentMeasureFlag(flag)) {
2008 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
2009 }
2010 }
2011
ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeFlag)2012 void FrameNode::ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeFlag)
2013 {
2014 layoutProperty_->UpdatePropertyChangeFlag(propertyChangeFlag);
2015 }
2016
AdjustParentLayoutFlag(PropertyChangeFlag & flag)2017 void FrameNode::AdjustParentLayoutFlag(PropertyChangeFlag& flag)
2018 {
2019 flag = flag | layoutProperty_->GetPropertyChangeFlag();
2020 }
2021
CreateLayoutWrapper(bool forceMeasure,bool forceLayout)2022 RefPtr<LayoutWrapperNode> FrameNode::CreateLayoutWrapper(bool forceMeasure, bool forceLayout)
2023 {
2024 return UpdateLayoutWrapper(nullptr, forceMeasure, forceLayout);
2025 }
2026
UpdateLayoutWrapper(RefPtr<LayoutWrapperNode> layoutWrapper,bool forceMeasure,bool forceLayout)2027 RefPtr<LayoutWrapperNode> FrameNode::UpdateLayoutWrapper(
2028 RefPtr<LayoutWrapperNode> layoutWrapper, bool forceMeasure, bool forceLayout)
2029 {
2030 CHECK_NULL_RETURN(layoutProperty_, nullptr);
2031 CHECK_NULL_RETURN(pattern_, nullptr);
2032 if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
2033 if (!layoutWrapper) {
2034 layoutWrapper =
2035 MakeRefPtr<LayoutWrapperNode>(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
2036 } else {
2037 layoutWrapper->Update(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
2038 }
2039 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
2040 isLayoutDirtyMarked_ = false;
2041 return layoutWrapper;
2042 }
2043
2044 pattern_->BeforeCreateLayoutWrapper();
2045 if (forceMeasure) {
2046 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
2047 }
2048 if (forceLayout) {
2049 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
2050 }
2051 auto flag = layoutProperty_->GetPropertyChangeFlag();
2052 // It is necessary to copy the layoutProperty property to prevent the layoutProperty property from being
2053 // modified during the layout process, resulting in the problem of judging whether the front-end setting value
2054 // changes the next time js is executed.
2055 if (!layoutWrapper) {
2056 layoutWrapper =
2057 MakeRefPtr<LayoutWrapperNode>(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
2058 } else {
2059 layoutWrapper->Update(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
2060 }
2061 do {
2062 if (CheckNeedMeasure(flag) || forceMeasure) {
2063 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm()));
2064 bool forceChildMeasure = CheckMeasureFlag(flag) || CheckMeasureSelfAndChildFlag(flag) || forceMeasure;
2065 UpdateChildrenLayoutWrapper(layoutWrapper, forceChildMeasure, false);
2066 break;
2067 }
2068 if (CheckNeedLayout(flag) || forceLayout) {
2069 layoutWrapper->SetLayoutAlgorithm(
2070 MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm(), true, false));
2071 UpdateChildrenLayoutWrapper(layoutWrapper, false, false);
2072 break;
2073 }
2074 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
2075 } while (false);
2076 // check position flag.
2077 layoutWrapper->SetOutOfLayout(renderContext_->HasPosition());
2078 layoutWrapper->SetActive(isActive_);
2079 layoutWrapper->SetIsOverlayNode(layoutProperty_->IsOverlayNode());
2080 isLayoutDirtyMarked_ = false;
2081 return layoutWrapper;
2082 }
2083
UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapperNode> & self,bool forceMeasure,bool forceLayout)2084 void FrameNode::UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapperNode>& self, bool forceMeasure, bool forceLayout)
2085 {
2086 const auto& children = GetChildren();
2087 for (const auto& child : children) {
2088 child->AdjustLayoutWrapperTree(self, forceMeasure, forceLayout);
2089 }
2090 }
2091
AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode> & parent,bool forceMeasure,bool forceLayout)2092 void FrameNode::AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode>& parent, bool forceMeasure, bool forceLayout)
2093 {
2094 ACE_DCHECK(parent);
2095 CHECK_NULL_VOID(layoutProperty_);
2096 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
2097 if (geometryTransition != nullptr && geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
2098 return;
2099 }
2100 auto layoutWrapper = CreateLayoutWrapper(forceMeasure, forceLayout);
2101 parent->AppendChild(layoutWrapper, layoutProperty_->IsOverlayNode());
2102 }
2103
GetContentModifier()2104 RefPtr<ContentModifier> FrameNode::GetContentModifier()
2105 {
2106 CHECK_NULL_RETURN(pattern_, nullptr);
2107 auto wrapper = CreatePaintWrapper();
2108 CHECK_NULL_RETURN(wrapper, nullptr);
2109 auto paintMethod = pattern_->CreateNodePaintMethod();
2110 if (!paintMethod || extensionHandler_ || renderContext_->GetAccessibilityFocus().value_or(false)) {
2111 paintMethod = pattern_->CreateDefaultNodePaintMethod();
2112 }
2113 CHECK_NULL_RETURN(paintMethod, nullptr);
2114 auto contentModifier = DynamicCast<ContentModifier>(paintMethod->GetContentModifier(AceType::RawPtr(wrapper)));
2115 return contentModifier;
2116 }
2117
CreatePaintWrapper()2118 RefPtr<PaintWrapper> FrameNode::CreatePaintWrapper()
2119 {
2120 pattern_->BeforeCreatePaintWrapper();
2121 isRenderDirtyMarked_ = false;
2122 auto paintMethod = pattern_->CreateNodePaintMethod();
2123 if (paintMethod || extensionHandler_ || renderContext_->GetAccessibilityFocus().value_or(false)) {
2124 // It is necessary to copy the layoutProperty property to prevent the paintProperty_ property from being
2125 // modified during the paint process, resulting in the problem of judging whether the front-end setting value
2126 // changes the next time js is executed.
2127 if (!paintMethod) {
2128 paintMethod = pattern_->CreateDefaultNodePaintMethod();
2129 }
2130
2131 auto paintWrapper = MakeRefPtr<PaintWrapper>(
2132 renderContext_, geometryNode_->Clone(), paintProperty_->Clone(), extensionHandler_);
2133 paintWrapper->SetNodePaintMethod(paintMethod);
2134 return paintWrapper;
2135 }
2136 return nullptr;
2137 }
2138
PostIdleTask(std::function<void (int64_t deadline,bool canUseLongPredictTask)> && task)2139 void FrameNode::PostIdleTask(std::function<void(int64_t deadline, bool canUseLongPredictTask)>&& task)
2140 {
2141 auto context = GetContext();
2142 CHECK_NULL_VOID(context);
2143 context->AddPredictTask(std::move(task));
2144 }
2145
UpdateLayoutConstraint(const MeasureProperty & calcLayoutConstraint)2146 void FrameNode::UpdateLayoutConstraint(const MeasureProperty& calcLayoutConstraint)
2147 {
2148 layoutProperty_->UpdateCalcLayoutProperty(calcLayoutConstraint);
2149 }
2150
RebuildRenderContextTree()2151 void FrameNode::RebuildRenderContextTree()
2152 {
2153 if (!needSyncRenderTree_) {
2154 return;
2155 }
2156 auto pipeline = GetContextRefPtr();
2157 if (pipeline && !pipeline->CheckThreadSafe()) {
2158 LOGW("RebuildRenderContextTree doesn't run on UI thread!");
2159 }
2160 frameChildren_.clear();
2161 std::list<RefPtr<FrameNode>> children;
2162 // generate full children list, including disappear children.
2163 GenerateOneDepthVisibleFrameWithTransition(children);
2164 if (overlayNode_) {
2165 auto property = overlayNode_->GetLayoutProperty();
2166 if (property && property->GetVisibilityValue(VisibleType::VISIBLE) == VisibleType::VISIBLE) {
2167 children.push_back(overlayNode_);
2168 }
2169 }
2170 for (const auto& child : children) {
2171 frameChildren_.emplace(child);
2172 }
2173 renderContext_->RebuildFrame(this, children);
2174 pattern_->OnRebuildFrame();
2175 needSyncRenderTree_ = false;
2176 }
2177
MarkModifyDone()2178 void FrameNode::MarkModifyDone()
2179 {
2180 pattern_->OnModifyDone();
2181 auto pipeline = PipelineContext::GetCurrentContextSafely();
2182 if (pipeline) {
2183 auto privacyManager = pipeline->GetPrivacySensitiveManager();
2184 if (privacyManager) {
2185 if (IsPrivacySensitive()) {
2186 LOGI("store sensitive node, %{public}d", GetId());
2187 privacyManager->StoreNode(AceType::WeakClaim(this));
2188 } else {
2189 privacyManager->RemoveNode(AceType::WeakClaim(this));
2190 }
2191 }
2192 }
2193 if (!isRestoreInfoUsed_) {
2194 isRestoreInfoUsed_ = true;
2195 int32_t restoreId = GetRestoreId();
2196 if (pipeline && restoreId >= 0) {
2197 // store distribute node
2198 pipeline->StoreNode(restoreId, AceType::WeakClaim(this));
2199 // restore distribute node info
2200 std::string restoreInfo;
2201 if (pipeline->GetRestoreInfo(restoreId, restoreInfo)) {
2202 pattern_->OnRestoreInfo(restoreInfo);
2203 }
2204 }
2205 }
2206 eventHub_->MarkModifyDone();
2207 renderContext_->OnModifyDone();
2208 #if (defined(__aarch64__) || defined(__x86_64__))
2209 if (Recorder::IsCacheAvaliable()) {
2210 auto pipeline = PipelineContext::GetCurrentContext();
2211 CHECK_NULL_VOID(pipeline);
2212 pipeline->AddAfterRenderTask([weak = WeakPtr(pattern_)]() {
2213 auto pattern = weak.Upgrade();
2214 CHECK_NULL_VOID(pattern);
2215 pattern->OnAfterModifyDone();
2216 });
2217 }
2218 #endif
2219 }
2220
OnMountToParentDone()2221 void FrameNode::OnMountToParentDone()
2222 {
2223 pattern_->OnMountToParentDone();
2224 }
2225
AfterMountToParent()2226 void FrameNode::AfterMountToParent()
2227 {
2228 if (pattern_) {
2229 pattern_->AfterMountToParent();
2230 }
2231 }
2232
FlushUpdateAndMarkDirty()2233 void FrameNode::FlushUpdateAndMarkDirty()
2234 {
2235 MarkDirtyNode();
2236 }
2237
MarkDirtyNode(PropertyChangeFlag extraFlag)2238 void FrameNode::MarkDirtyNode(PropertyChangeFlag extraFlag)
2239 {
2240 if (IsFreeze()) {
2241 // store the flag.
2242 layoutProperty_->UpdatePropertyChangeFlag(extraFlag);
2243 paintProperty_->UpdatePropertyChangeFlag(extraFlag);
2244 return;
2245 }
2246 if (CheckNeedMakePropertyDiff(extraFlag)) {
2247 if (isPropertyDiffMarked_) {
2248 return;
2249 }
2250 auto context = GetContextWithCheck();
2251 CHECK_NULL_VOID(context);
2252 context->AddDirtyPropertyNode(Claim(this));
2253 isPropertyDiffMarked_ = true;
2254 return;
2255 }
2256 MarkDirtyNode(IsMeasureBoundary(), IsRenderBoundary(), extraFlag);
2257 }
2258
ProcessFreezeNode()2259 void FrameNode::ProcessFreezeNode()
2260 {
2261 MarkDirtyNode();
2262 }
2263
OnFreezeStateChange()2264 void FrameNode::OnFreezeStateChange()
2265 {
2266 if (IsFreeze()) {
2267 return;
2268 }
2269 // unlock freeze, mark dirty to process freeze node.
2270 auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
2271 auto paintFlag = paintProperty_->GetPropertyChangeFlag();
2272 if (CheckNoChanged(layoutFlag | paintFlag)) {
2273 return;
2274 }
2275 auto pipeline = GetContext();
2276 CHECK_NULL_VOID(pipeline);
2277 pipeline->AddDirtyFreezeNode(this);
2278 }
2279
GetAncestorNodeOfFrame(bool checkBoundary) const2280 RefPtr<FrameNode> FrameNode::GetAncestorNodeOfFrame(bool checkBoundary) const
2281 {
2282 if (checkBoundary && IsWindowBoundary()) {
2283 return nullptr;
2284 }
2285 auto parent = GetParent();
2286 while (parent) {
2287 auto parentFrame = DynamicCast<FrameNode>(parent);
2288 if (parentFrame) {
2289 return parentFrame;
2290 }
2291 parent = parent->GetParent();
2292 }
2293 return nullptr;
2294 }
2295
GetPageNode()2296 RefPtr<FrameNode> FrameNode::GetPageNode()
2297 {
2298 if (GetTag() == "page") {
2299 return Claim(this);
2300 }
2301 auto parent = GetParent();
2302 while (parent && parent->GetTag() != "page") {
2303 parent = parent->GetParent();
2304 }
2305 return AceType::DynamicCast<FrameNode>(parent);
2306 }
2307
GetFirstAutoFillContainerNode()2308 RefPtr<FrameNode> FrameNode::GetFirstAutoFillContainerNode()
2309 {
2310 if (IsAutoFillContainerNode()) {
2311 return Claim(this);
2312 }
2313 auto parent = GetParent();
2314 while (parent && !parent->IsAutoFillContainerNode()) {
2315 parent = parent->GetParent();
2316 }
2317 return AceType::DynamicCast<FrameNode>(parent);
2318 }
2319
NotifyFillRequestSuccess(RefPtr<ViewDataWrap> viewDataWrap,RefPtr<PageNodeInfoWrap> nodeWrap,AceAutoFillType autoFillType)2320 void FrameNode::NotifyFillRequestSuccess(
2321 RefPtr<ViewDataWrap> viewDataWrap, RefPtr<PageNodeInfoWrap> nodeWrap, AceAutoFillType autoFillType)
2322 {
2323 if (pattern_) {
2324 pattern_->NotifyFillRequestSuccess(viewDataWrap, nodeWrap, autoFillType);
2325 }
2326 }
2327
NotifyFillRequestFailed(int32_t errCode,const std::string & fillContent,bool isPopup)2328 void FrameNode::NotifyFillRequestFailed(int32_t errCode, const std::string& fillContent, bool isPopup)
2329 {
2330 if (pattern_) {
2331 pattern_->NotifyFillRequestFailed(errCode, fillContent, isPopup);
2332 }
2333 }
2334
MarkNeedRenderOnly()2335 void FrameNode::MarkNeedRenderOnly()
2336 {
2337 MarkNeedRender(IsRenderBoundary());
2338 }
2339
MarkNeedRender(bool isRenderBoundary)2340 void FrameNode::MarkNeedRender(bool isRenderBoundary)
2341 {
2342 auto context = GetContext();
2343 CHECK_NULL_VOID(context);
2344 // If it has dirtyLayoutBox, need to mark dirty after layout done.
2345 paintProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_RENDER);
2346 if (isRenderDirtyMarked_ || isLayoutDirtyMarked_) {
2347 return;
2348 }
2349 isRenderDirtyMarked_ = true;
2350 if (isRenderBoundary) {
2351 context->AddDirtyRenderNode(Claim(this));
2352 return;
2353 }
2354 auto parent = GetAncestorNodeOfFrame();
2355 if (parent) {
2356 parent->MarkDirtyNode(PROPERTY_UPDATE_RENDER_BY_CHILD_REQUEST);
2357 }
2358 }
2359
RequestParentDirty()2360 bool FrameNode::RequestParentDirty()
2361 {
2362 auto parent = GetAncestorNodeOfFrame();
2363 CHECK_NULL_RETURN(parent, false);
2364 parent->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
2365 return true;
2366 }
2367
MarkDirtyNode(bool isMeasureBoundary,bool isRenderBoundary,PropertyChangeFlag extraFlag)2368 void FrameNode::MarkDirtyNode(bool isMeasureBoundary, bool isRenderBoundary, PropertyChangeFlag extraFlag)
2369 {
2370 layoutProperty_->UpdatePropertyChangeFlag(extraFlag);
2371 paintProperty_->UpdatePropertyChangeFlag(extraFlag);
2372 auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
2373 auto paintFlag = paintProperty_->GetPropertyChangeFlag();
2374 if (CheckNoChanged(layoutFlag | paintFlag)) {
2375 return;
2376 }
2377 auto context = GetContext();
2378 CHECK_NULL_VOID(context);
2379
2380 if (CheckNeedRequestMeasureAndLayout(layoutFlag)) {
2381 if ((!isMeasureBoundary && IsNeedRequestParentMeasure())) {
2382 if (RequestParentDirty()) {
2383 return;
2384 }
2385 }
2386 if (isLayoutDirtyMarked_) {
2387 return;
2388 }
2389 isLayoutDirtyMarked_ = true;
2390 context->AddDirtyLayoutNode(Claim(this));
2391 return;
2392 }
2393 layoutProperty_->CleanDirty();
2394 MarkNeedRender(isRenderBoundary);
2395 }
2396
IsNeedRequestParentMeasure() const2397 bool FrameNode::IsNeedRequestParentMeasure() const
2398 {
2399 auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
2400 if (layoutFlag == PROPERTY_UPDATE_BY_CHILD_REQUEST) {
2401 const auto& calcLayoutConstraint = layoutProperty_->GetCalcLayoutConstraint();
2402 if (calcLayoutConstraint && calcLayoutConstraint->selfIdealSize &&
2403 calcLayoutConstraint->selfIdealSize->IsValid()) {
2404 return false;
2405 }
2406 }
2407 return CheckNeedRequestParentMeasure(layoutFlag);
2408 }
2409
OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & visibleList)2410 void FrameNode::OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& visibleList)
2411 {
2412 if (isLayoutNode_) {
2413 UINode::GenerateOneDepthVisibleFrame(visibleList);
2414 if (overlayNode_) {
2415 visibleList.emplace_back(overlayNode_);
2416 }
2417 return;
2418 }
2419 if (isActive_ && IsVisible()) {
2420 visibleList.emplace_back(Claim(this));
2421 }
2422 }
2423
OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>> & allList)2424 void FrameNode::OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>>& allList)
2425 {
2426 allList.emplace_back(Claim(this));
2427 }
2428
OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>> & visibleList)2429 void FrameNode::OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>>& visibleList)
2430 {
2431 if (isLayoutNode_) {
2432 UINode::GenerateOneDepthVisibleFrameWithTransition(visibleList);
2433 if (overlayNode_) {
2434 visibleList.emplace_back(overlayNode_);
2435 }
2436 return;
2437 }
2438
2439 auto context = GetRenderContext();
2440 CHECK_NULL_VOID(context);
2441 // skip if 1.not active or 2.not visible and has no transition out animation.
2442 if (!isActive_ || (!IsVisible() && !context->HasTransitionOutAnimation())) {
2443 return;
2444 }
2445 visibleList.emplace_back(Claim(this));
2446 }
2447
OnGenerateOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>> & visibleList,OffsetF & offset)2448 void FrameNode::OnGenerateOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>>& visibleList, OffsetF& offset)
2449 {
2450 if (isLayoutNode_) {
2451 isFind_ = true;
2452 offset += GetGeometryNode()->GetFrameOffset();
2453 UINode::GenerateOneDepthVisibleFrameWithOffset(visibleList, offset);
2454 if (overlayNode_) {
2455 visibleList.emplace_back(overlayNode_);
2456 }
2457 return;
2458 }
2459
2460 auto context = GetRenderContext();
2461 CHECK_NULL_VOID(context);
2462 // skip if 1.not active or 2.not visible and has no transition out animation.
2463 if (!isActive_ || (!IsVisible() && !context->HasTransitionOutAnimation())) {
2464 return;
2465 }
2466 visibleList.emplace_back(Claim(this));
2467 }
2468
IsMeasureBoundary()2469 bool FrameNode::IsMeasureBoundary()
2470 {
2471 return isMeasureBoundary_ || pattern_->IsMeasureBoundary();
2472 }
2473
IsRenderBoundary()2474 bool FrameNode::IsRenderBoundary()
2475 {
2476 return pattern_->IsRenderBoundary();
2477 }
2478
GetPattern() const2479 const RefPtr<Pattern>& FrameNode::GetPattern() const
2480 {
2481 return pattern_;
2482 }
2483
IsAtomicNode() const2484 bool FrameNode::IsAtomicNode() const
2485 {
2486 return pattern_->IsAtomicNode();
2487 }
2488
GetHitTestMode() const2489 HitTestMode FrameNode::GetHitTestMode() const
2490 {
2491 auto gestureHub = eventHub_->GetGestureEventHub();
2492 return gestureHub ? gestureHub->GetHitTestMode() : HitTestMode::HTMDEFAULT;
2493 }
2494
SetHitTestMode(HitTestMode mode)2495 void FrameNode::SetHitTestMode(HitTestMode mode)
2496 {
2497 auto gestureHub = eventHub_->GetOrCreateGestureEventHub();
2498 CHECK_NULL_VOID(gestureHub);
2499 gestureHub->SetHitTestMode(mode);
2500 }
2501
GetTouchable() const2502 bool FrameNode::GetTouchable() const
2503 {
2504 auto gestureHub = eventHub_->GetGestureEventHub();
2505 return gestureHub ? gestureHub->GetTouchable() : true;
2506 }
2507
GetMonopolizeEvents() const2508 bool FrameNode::GetMonopolizeEvents() const
2509 {
2510 auto gestureHub = eventHub_->GetGestureEventHub();
2511 return gestureHub ? gestureHub->GetMonopolizeEvents() : false;
2512 }
2513
GetPaintRectWithTransform() const2514 RectF FrameNode::GetPaintRectWithTransform() const
2515 {
2516 return renderContext_->GetPaintRectWithTransform();
2517 }
2518
GetTransformScale() const2519 VectorF FrameNode::GetTransformScale() const
2520 {
2521 return renderContext_->GetTransformScaleValue({ 1.0f, 1.0f });
2522 }
2523
IsPaintRectWithTransformValid()2524 bool FrameNode::IsPaintRectWithTransformValid()
2525 {
2526 auto paintRectWithTransform = renderContext_->GetPaintRectWithTransform();
2527 if (NearZero(paintRectWithTransform.Width()) || NearZero(paintRectWithTransform.Height())) {
2528 return true;
2529 }
2530 return false;
2531 }
2532
IsOutOfTouchTestRegion(const PointF & parentRevertPoint,const TouchEvent & touchEvent)2533 bool FrameNode::IsOutOfTouchTestRegion(const PointF& parentRevertPoint, const TouchEvent& touchEvent)
2534 {
2535 bool isInChildRegion = false;
2536 auto paintRect = renderContext_->GetPaintRectWithoutTransform();
2537 if (pattern_->IsResponseRegionExpandingNeededForStylus(touchEvent)) {
2538 paintRect = pattern_->ExpandDefaultResponseRegion(paintRect);
2539 }
2540 auto responseRegionList = GetResponseRegionList(paintRect, static_cast<int32_t>(touchEvent.sourceType));
2541
2542 auto revertPoint = parentRevertPoint;
2543 MapPointTo(revertPoint, GetOrRefreshRevertMatrixFromCache());
2544 auto subRevertPoint = revertPoint - paintRect.GetOffset();
2545 auto clip = renderContext_->GetClipEdge().value_or(false);
2546 if (!InResponseRegionList(revertPoint, responseRegionList) || !GetTouchable() ||
2547 IsPaintRectWithTransformValid()) {
2548 if (clip) {
2549 return true;
2550 }
2551 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
2552 const auto& child = iter->Upgrade();
2553 if (child && !child->IsOutOfTouchTestRegion(subRevertPoint, touchEvent)) {
2554 isInChildRegion = true;
2555 break;
2556 }
2557 }
2558 if (!isInChildRegion) {
2559 return true;
2560 }
2561 }
2562 return false;
2563 }
2564
AddJudgeToTargetComponent(RefPtr<TargetComponent> & targetComponent)2565 void FrameNode::AddJudgeToTargetComponent(RefPtr<TargetComponent>& targetComponent)
2566 {
2567 auto gestureHub = eventHub_->GetGestureEventHub();
2568 if (gestureHub) {
2569 auto callback = gestureHub->GetOnGestureJudgeBeginCallback();
2570 targetComponent->SetOnGestureJudgeBegin(std::move(callback));
2571 auto callbackNative = gestureHub->GetOnGestureJudgeNativeBeginCallback();
2572 if (callbackNative) {
2573 targetComponent->SetOnGestureJudgeNativeBegin(std::move(callbackNative));
2574 }
2575
2576 if (!targetComponent->IsInnerNodeGestureRecognizerJudgeSet()) {
2577 auto gestureRecognizerJudgeCallback = gestureHub->GetOnGestureRecognizerJudgeBegin();
2578 targetComponent->SetOnGestureRecognizerJudgeBegin(std::move(gestureRecognizerJudgeCallback));
2579 }
2580
2581 if (GetExposeInnerGestureFlag()) {
2582 auto pattern = GetPattern();
2583 if (pattern) {
2584 auto gestureRecognizerJudgeCallback = gestureHub->GetOnGestureRecognizerJudgeBegin();
2585 pattern->AddInnerOnGestureRecognizerJudgeBegin(std::move(gestureRecognizerJudgeCallback));
2586 }
2587 }
2588 }
2589 }
2590
TouchTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,TouchRestrict & touchRestrict,TouchTestResult & result,int32_t touchId,ResponseLinkResult & responseLinkResult,bool isDispatch)2591 HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& parentLocalPoint,
2592 const PointF& parentRevertPoint, TouchRestrict& touchRestrict, TouchTestResult& result, int32_t touchId,
2593 ResponseLinkResult& responseLinkResult, bool isDispatch)
2594 {
2595 if (!isActive_ || !eventHub_->IsEnabled()) {
2596 TAG_LOGW(AceLogTag::ACE_UIEVENT, "%{public}s is inActive, need't do touch test", GetTag().c_str());
2597 return HitTestResult::OUT_OF_REGION;
2598 }
2599 auto paintRect = renderContext_->GetPaintRectWithTransform();
2600 auto origRect = renderContext_->GetPaintRectWithoutTransform();
2601 auto localMat = renderContext_->GetLocalTransformMatrix();
2602 if (!touchRestrict.touchEvent.isMouseTouchTest) {
2603 localMat_ = localMat;
2604 }
2605 int32_t parentId = -1;
2606 auto parent = GetAncestorNodeOfFrame();
2607 if (parent) {
2608 parentId = parent->GetId();
2609 }
2610
2611 if (pattern_->IsResponseRegionExpandingNeededForStylus(touchRestrict.touchEvent)) {
2612 origRect = pattern_->ExpandDefaultResponseRegion(origRect);
2613 }
2614 auto responseRegionList = GetResponseRegionList(origRect, static_cast<int32_t>(touchRestrict.sourceType));
2615 if (SystemProperties::GetDebugEnabled()) {
2616 TAG_LOGD(AceLogTag::ACE_UIEVENT, "TouchTest: point is %{public}s in %{public}s, depth: %{public}d",
2617 parentRevertPoint.ToString().c_str(), GetTag().c_str(), GetDepth());
2618 for (const auto& rect : responseRegionList) {
2619 TAG_LOGD(AceLogTag::ACE_UIEVENT, "TouchTest: responseRegionList is %{public}s, point is %{public}s",
2620 rect.ToString().c_str(), parentRevertPoint.ToString().c_str());
2621 }
2622 }
2623 {
2624 ACE_DEBUG_SCOPED_TRACE("FrameNode::IsOutOfTouchTestRegion");
2625 bool isOutOfRegion = IsOutOfTouchTestRegion(parentRevertPoint, touchRestrict.touchEvent);
2626 AddFrameNodeSnapshot(!isOutOfRegion, parentId, responseRegionList, touchRestrict.touchTestType);
2627 if ((!isDispatch) && isOutOfRegion) {
2628 return HitTestResult::OUT_OF_REGION;
2629 }
2630 }
2631
2632 RefPtr<TargetComponent> targetComponent;
2633 if (targetComponent_.Upgrade()) {
2634 targetComponent = targetComponent_.Upgrade();
2635 } else {
2636 targetComponent = MakeRefPtr<TargetComponent>();
2637 targetComponent_ = targetComponent;
2638 }
2639 targetComponent->SetNode(WeakClaim(this));
2640
2641 HitTestResult testResult = HitTestResult::OUT_OF_REGION;
2642 bool preventBubbling = false;
2643 // Child nodes are repackaged into gesture groups (parallel gesture groups, exclusive gesture groups, etc.)
2644 // based on the gesture attributes set by the current parent node (high and low priority, parallel gestures,
2645 // etc.), the newComingTargets is the template object to collect child nodes gesture and used by gestureHub to
2646 // pack gesture group.
2647 TouchTestResult newComingTargets;
2648 auto tmp = parentLocalPoint - paintRect.GetOffset();
2649 auto preLocation = tmp;
2650 renderContext_->GetPointWithTransform(tmp);
2651 const auto localPoint = tmp;
2652 auto localTransformOffset = preLocation - localPoint;
2653
2654 auto revertPoint = parentRevertPoint;
2655 MapPointTo(revertPoint, GetOrRefreshRevertMatrixFromCache());
2656 auto subRevertPoint = revertPoint - origRect.GetOffset();
2657 bool consumed = false;
2658
2659 HitTestMode onTouchInterceptresult = HitTestMode::HTMDEFAULT;
2660 if (touchRestrict.inputEventType != InputEventType::MOUSE_BUTTON) {
2661 onTouchInterceptresult = TriggerOnTouchIntercept(touchRestrict.touchEvent);
2662 }
2663 TouchResult touchRes;
2664 if (onTouchInterceptresult != HitTestMode::HTMBLOCK) {
2665 std::vector<TouchTestInfo> touchInfos;
2666 CollectTouchInfos(globalPoint, subRevertPoint, touchInfos);
2667 touchRes = GetOnChildTouchTestRet(touchInfos);
2668 if ((touchRes.strategy != TouchTestStrategy::DEFAULT) && touchRes.id.empty()) {
2669 TAG_LOGW(AceLogTag::ACE_UIEVENT, "onChildTouchTest result is: id = %{public}s, strategy = %{public}d.",
2670 touchRes.id.c_str(), static_cast<int32_t>(touchRes.strategy));
2671 touchRes.strategy = TouchTestStrategy::DEFAULT;
2672 }
2673
2674 auto childNode = GetDispatchFrameNode(touchRes);
2675 if (childNode != nullptr) {
2676 TAG_LOGD(AceLogTag::ACE_UIEVENT, "%{public}s do TouchTest, parameter isDispatch is true.",
2677 childNode->GetInspectorId()->c_str());
2678 auto hitResult = childNode->TouchTest(globalPoint, localPoint, subRevertPoint, touchRestrict,
2679 newComingTargets, touchId, responseLinkResult, true);
2680 if (touchRes.strategy == TouchTestStrategy::FORWARD ||
2681 touchRes.strategy == TouchTestStrategy::FORWARD_COMPETITION) {
2682 touchRestrict.childTouchTestList.emplace_back(touchRes.id);
2683 }
2684 if (hitResult == HitTestResult::STOP_BUBBLING) {
2685 preventBubbling = true;
2686 consumed = true;
2687 }
2688
2689 if (hitResult == HitTestResult::BUBBLING) {
2690 consumed = true;
2691 }
2692 }
2693 }
2694
2695 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
2696 if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
2697 break;
2698 }
2699 if (onTouchInterceptresult != HitTestMode::HTMBLOCK) {
2700 if (touchRes.strategy == TouchTestStrategy::FORWARD) {
2701 break;
2702 }
2703 }
2704
2705 const auto& child = iter->Upgrade();
2706 if (!child) {
2707 continue;
2708 }
2709 if (onTouchInterceptresult != HitTestMode::HTMBLOCK) {
2710 std::string id;
2711 if (child->GetInspectorId().has_value()) {
2712 id = child->GetInspectorId().value();
2713 }
2714 if (touchRes.strategy == TouchTestStrategy::FORWARD_COMPETITION && touchRes.id == id) {
2715 continue;
2716 }
2717 }
2718
2719 auto childHitResult = child->TouchTest(
2720 globalPoint, localPoint, subRevertPoint, touchRestrict, newComingTargets, touchId, responseLinkResult);
2721 if (childHitResult == HitTestResult::STOP_BUBBLING) {
2722 preventBubbling = true;
2723 consumed = true;
2724 if ((child->GetHitTestMode() == HitTestMode::HTMBLOCK) ||
2725 (child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
2726 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
2727 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && IsExclusiveEventForChild())) {
2728 break;
2729 }
2730 }
2731
2732 // In normal process, the node block the brother node.
2733 if (childHitResult == HitTestResult::BUBBLING &&
2734 ((child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
2735 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
2736 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && IsExclusiveEventForChild()))) {
2737 consumed = true;
2738 break;
2739 }
2740 }
2741
2742 AddJudgeToTargetComponent(targetComponent);
2743
2744 // first update HitTestResult by children status.
2745 if (consumed) {
2746 testResult = preventBubbling ? HitTestResult::STOP_BUBBLING : HitTestResult::BUBBLING;
2747 consumed = false;
2748 } else if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
2749 testResult = HitTestResult::STOP_BUBBLING;
2750 }
2751
2752 if (!preventBubbling && (GetHitTestMode() != HitTestMode::HTMNONE) &&
2753 (isDispatch || (InResponseRegionList(revertPoint, responseRegionList)))) {
2754 pattern_->OnTouchTestHit(touchRestrict.hitTestType);
2755 consumed = true;
2756 if (touchRestrict.hitTestType == SourceType::TOUCH) {
2757 auto gestureHub = eventHub_->GetGestureEventHub();
2758 if (gestureHub) {
2759 TouchTestResult finalResult;
2760 ResponseLinkResult newComingResponseLinkTargets;
2761 const auto coordinateOffset = globalPoint - localPoint - localTransformOffset;
2762 preventBubbling = gestureHub->ProcessTouchTestHit(coordinateOffset, touchRestrict, newComingTargets,
2763 finalResult, touchId, localPoint, targetComponent, newComingResponseLinkTargets);
2764 newComingTargets.swap(finalResult);
2765 TriggerShouldParallelInnerWith(newComingResponseLinkTargets, responseLinkResult);
2766 responseLinkResult.splice(responseLinkResult.end(), std::move(newComingResponseLinkTargets));
2767 }
2768 } else if (touchRestrict.hitTestType == SourceType::MOUSE) {
2769 preventBubbling = ProcessMouseTestHit(globalPoint, localPoint, touchRestrict, newComingTargets);
2770 }
2771 }
2772
2773 result.splice(result.end(), std::move(newComingTargets));
2774 if (touchRestrict.hitTestType == SourceType::TOUCH) {
2775 // combine into exclusive recognizer group.
2776 auto gestureHub = eventHub_->GetGestureEventHub();
2777 if (gestureHub) {
2778 gestureHub->CombineIntoExclusiveRecognizer(globalPoint, localPoint, result, touchId);
2779 }
2780 }
2781
2782 // consumed by children and return result.
2783 if (!consumed) {
2784 return testResult;
2785 }
2786
2787 if (testResult == HitTestResult::OUT_OF_REGION) {
2788 // consume only by self.
2789 if (preventBubbling) {
2790 return HitTestResult::STOP_BUBBLING;
2791 }
2792 return (GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ? HitTestResult::SELF_TRANSPARENT
2793 : HitTestResult::BUBBLING;
2794 }
2795 // consume by self and children.
2796 return testResult;
2797 }
2798
ProcessMouseTestHit(const PointF & globalPoint,const PointF & localPoint,TouchRestrict & touchRestrict,TouchTestResult & newComingTargets)2799 bool FrameNode::ProcessMouseTestHit(const PointF& globalPoint, const PointF& localPoint,
2800 TouchRestrict& touchRestrict, TouchTestResult& newComingTargets)
2801 {
2802 auto mouseHub = eventHub_->GetInputEventHub();
2803 if (!mouseHub) {
2804 return false;
2805 }
2806
2807 const auto coordinateOffset = globalPoint - localPoint;
2808 if (touchRestrict.touchEvent.IsPenHoverEvent()) {
2809 return mouseHub->ProcessPenHoverTestHit(coordinateOffset, newComingTargets);
2810 }
2811
2812 return mouseHub->ProcessMouseTestHit(coordinateOffset, newComingTargets);
2813 }
2814
GetResponseRegionList(const RectF & rect,int32_t sourceType)2815 std::vector<RectF> FrameNode::GetResponseRegionList(const RectF& rect, int32_t sourceType)
2816 {
2817 std::vector<RectF> responseRegionList;
2818 auto gestureHub = eventHub_->GetGestureEventHub();
2819 if (!gestureHub) {
2820 responseRegionList.emplace_back(rect);
2821 return responseRegionList;
2822 }
2823 auto scaleProperty = ScaleProperty::CreateScaleProperty();
2824 bool isMouseEvent = (static_cast<SourceType>(sourceType) == SourceType::MOUSE);
2825 if (isMouseEvent) {
2826 if (gestureHub->GetResponseRegion().empty() && (gestureHub->GetMouseResponseRegion().empty())) {
2827 responseRegionList.emplace_back(rect);
2828 return responseRegionList;
2829 }
2830 } else {
2831 if (gestureHub->GetResponseRegion().empty()) {
2832 responseRegionList.emplace_back(rect);
2833 return responseRegionList;
2834 }
2835 }
2836
2837 if (isMouseEvent && (!gestureHub->GetMouseResponseRegion().empty())) {
2838 for (const auto& region : gestureHub->GetMouseResponseRegion()) {
2839 auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
2840 auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
2841 auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
2842 auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
2843 if (!x.has_value() || !y.has_value() || !width.has_value() || !height.has_value()) {
2844 continue;
2845 }
2846 RectF mouseRegion(rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(),
2847 height.value());
2848 responseRegionList.emplace_back(mouseRegion);
2849 }
2850 return responseRegionList;
2851 }
2852 for (const auto& region : gestureHub->GetResponseRegion()) {
2853 auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
2854 auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
2855 auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
2856 auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
2857 if (!x.has_value() || !y.has_value() || !width.has_value() || !height.has_value()) {
2858 continue;
2859 }
2860 RectF responseRegion(
2861 rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(), height.value());
2862 responseRegionList.emplace_back(responseRegion);
2863 }
2864 return responseRegionList;
2865 }
2866
GetResponseRegionListForRecognizer(int32_t sourceType)2867 std::vector<RectF> FrameNode::GetResponseRegionListForRecognizer(int32_t sourceType)
2868 {
2869 auto paintRect = renderContext_->GetPaintRectWithoutTransform();
2870 auto responseRegionList = GetResponseRegionList(paintRect, sourceType);
2871 return responseRegionList;
2872 }
2873
GetResponseRegionListForTouch(const RectF & rect)2874 std::vector<RectF> FrameNode::GetResponseRegionListForTouch(const RectF& rect)
2875 {
2876 ACE_LAYOUT_TRACE_BEGIN("GetResponseRegionListForTouch");
2877 std::vector<RectF> responseRegionList;
2878 auto gestureHub = eventHub_->GetGestureEventHub();
2879 if (!gestureHub) {
2880 ACE_LAYOUT_TRACE_END()
2881 return responseRegionList;
2882 }
2883
2884 bool isAccessibilityClickable = gestureHub->IsAccessibilityClickable();
2885 if (!isAccessibilityClickable) {
2886 ACE_LAYOUT_TRACE_END()
2887 return responseRegionList;
2888 }
2889 auto offset = GetPositionToScreen();
2890 if (gestureHub->GetResponseRegion().empty()) {
2891 RectF rectToScreen{round(offset.GetX()), round(offset.GetY()), round(rect.Width()), round(rect.Height())};
2892 responseRegionList.emplace_back(rectToScreen);
2893 ACE_LAYOUT_TRACE_END()
2894 return responseRegionList;
2895 }
2896
2897 auto scaleProperty = ScaleProperty::CreateScaleProperty();
2898 for (const auto& region : gestureHub->GetResponseRegion()) {
2899 auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
2900 auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
2901 auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
2902 auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
2903 RectF responseRegion(round(offset.GetX() + x.value()), round(offset.GetY() + y.value()),
2904 round(width.value()), round(height.value()));
2905 responseRegionList.emplace_back(responseRegion);
2906 }
2907 ACE_LAYOUT_TRACE_END()
2908 return responseRegionList;
2909 }
2910
GetResponseRegionListByTraversal(std::vector<RectF> & responseRegionList)2911 void FrameNode::GetResponseRegionListByTraversal(std::vector<RectF>& responseRegionList)
2912 {
2913 CHECK_NULL_VOID(renderContext_);
2914 auto origRect = renderContext_->GetPaintRectWithoutTransform();
2915 auto pipelineContext = GetContext();
2916 CHECK_NULL_VOID(pipelineContext);
2917 auto offset = GetPositionToScreen();
2918 RectF rectToScreen{offset.GetX(), offset.GetY(), origRect.Width(), origRect.Height()};
2919 auto window = pipelineContext->GetCurrentWindowRect();
2920 RectF windowRect{window.Left(), window.Top(), window.Width(), window.Height()};
2921
2922 if (rectToScreen.Left() >= windowRect.Right() || rectToScreen.Right() <= windowRect.Left() ||
2923 rectToScreen.Top() >= windowRect.Bottom() || rectToScreen.Bottom() <= windowRect.Top()) {
2924 return;
2925 }
2926
2927 auto rootRegionList = GetResponseRegionListForTouch(origRect);
2928 if (!rootRegionList.empty()) {
2929 for (auto rect : rootRegionList) {
2930 responseRegionList.push_back(rect.IntersectRectT(windowRect));
2931 }
2932 return;
2933 }
2934 for (auto childWeak = frameChildren_.rbegin(); childWeak != frameChildren_.rend(); ++childWeak) {
2935 const auto& child = childWeak->Upgrade();
2936 if (!child) {
2937 continue;
2938 }
2939 child->GetResponseRegionListByTraversal(responseRegionList);
2940 }
2941 }
2942
InResponseRegionList(const PointF & parentLocalPoint,const std::vector<RectF> & responseRegionList) const2943 bool FrameNode::InResponseRegionList(const PointF& parentLocalPoint, const std::vector<RectF>& responseRegionList) const
2944 {
2945 for (const auto& rect : responseRegionList) {
2946 if (rect.IsInRegion(parentLocalPoint)) {
2947 return true;
2948 }
2949 }
2950 return false;
2951 }
2952
MouseTest(const PointF & globalPoint,const PointF & parentLocalPoint,MouseTestResult & onMouseResult,MouseTestResult & onHoverResult,RefPtr<FrameNode> & hoverNode)2953 HitTestResult FrameNode::MouseTest(const PointF& globalPoint, const PointF& parentLocalPoint,
2954 MouseTestResult& onMouseResult, MouseTestResult& onHoverResult, RefPtr<FrameNode>& hoverNode)
2955 {
2956 // unuseable function. do nothing.
2957 return HitTestResult::BUBBLING;
2958 }
2959
AxisTest(const PointF & globalPoint,const PointF & parentLocalPoint,AxisTestResult & onAxisResult)2960 HitTestResult FrameNode::AxisTest(
2961 const PointF& globalPoint, const PointF& parentLocalPoint, AxisTestResult& onAxisResult)
2962 {
2963 const auto& rect = renderContext_->GetPaintRectWithTransform();
2964
2965 if (!rect.IsInRegion(parentLocalPoint)) {
2966 return HitTestResult::OUT_OF_REGION;
2967 }
2968
2969 bool preventBubbling = false;
2970
2971 const auto localPoint = parentLocalPoint - rect.GetOffset();
2972 const auto& children = GetChildren();
2973 for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
2974 auto& child = *iter;
2975 auto childHitResult = child->AxisTest(globalPoint, localPoint, onAxisResult);
2976 if (childHitResult == HitTestResult::STOP_BUBBLING) {
2977 preventBubbling = true;
2978 }
2979 // In normal process, the node block the brother node.
2980 if (childHitResult == HitTestResult::BUBBLING) {
2981 // TODO: add hit test mode judge.
2982 break;
2983 }
2984 }
2985
2986 AxisTestResult axisResult;
2987 bool isPrevent = false;
2988 auto inputHub = eventHub_->GetInputEventHub();
2989 if (inputHub) {
2990 const auto coordinateOffset = globalPoint - localPoint;
2991 isPrevent = inputHub->ProcessAxisTestHit(coordinateOffset, axisResult);
2992 }
2993
2994 if (!preventBubbling) {
2995 preventBubbling = isPrevent;
2996 onAxisResult.splice(onAxisResult.end(), std::move(axisResult));
2997 }
2998 if (preventBubbling) {
2999 return HitTestResult::STOP_BUBBLING;
3000 }
3001 return HitTestResult::BUBBLING;
3002 }
3003
AnimateHoverEffect(bool isHovered) const3004 void FrameNode::AnimateHoverEffect(bool isHovered) const
3005 {
3006 auto renderContext = GetRenderContext();
3007 if (!renderContext) {
3008 return;
3009 }
3010 HoverEffectType animationType = HoverEffectType::UNKNOWN;
3011 auto inputEventHub = eventHub_->GetInputEventHub();
3012 if (inputEventHub) {
3013 animationType = inputEventHub->GetHoverEffect();
3014 if (animationType == HoverEffectType::UNKNOWN || animationType == HoverEffectType::AUTO) {
3015 animationType = inputEventHub->GetHoverEffectAuto();
3016 }
3017 }
3018 if (animationType == HoverEffectType::SCALE) {
3019 renderContext->AnimateHoverEffectScale(isHovered);
3020 } else if (animationType == HoverEffectType::BOARD) {
3021 renderContext->AnimateHoverEffectBoard(isHovered);
3022 }
3023 }
3024
GetOrCreateFocusHub() const3025 RefPtr<FocusHub> FrameNode::GetOrCreateFocusHub() const
3026 {
3027 if (!pattern_) {
3028 return eventHub_->GetOrCreateFocusHub();
3029 }
3030 auto focusPattern = pattern_->GetFocusPattern();
3031 return eventHub_->GetOrCreateFocusHub(focusPattern);
3032 }
3033
OnWindowShow()3034 void FrameNode::OnWindowShow()
3035 {
3036 pattern_->OnWindowShow();
3037 }
3038
OnWindowHide()3039 void FrameNode::OnWindowHide()
3040 {
3041 pattern_->OnWindowHide();
3042 }
3043
OnWindowFocused()3044 void FrameNode::OnWindowFocused()
3045 {
3046 pattern_->OnWindowFocused();
3047 }
3048
OnWindowUnfocused()3049 void FrameNode::OnWindowUnfocused()
3050 {
3051 pattern_->OnWindowUnfocused();
3052 }
3053
ContextPositionConvertToPX(const RefPtr<RenderContext> & context,const SizeF & percentReference)3054 std::pair<float, float> FrameNode::ContextPositionConvertToPX(
3055 const RefPtr<RenderContext>& context, const SizeF& percentReference)
3056 {
3057 std::pair<float, float> position;
3058 CHECK_NULL_RETURN(context, position);
3059 auto scaleProperty = ScaleProperty::CreateScaleProperty();
3060 position.first =
3061 ConvertToPx(context->GetPositionProperty()->GetPosition()->GetX(), scaleProperty, percentReference.Width())
3062 .value_or(0.0);
3063 position.second =
3064 ConvertToPx(context->GetPositionProperty()->GetPosition()->GetY(), scaleProperty, percentReference.Height())
3065 .value_or(0.0);
3066 return position;
3067 }
3068
OnPixelRoundFinish(const SizeF & pixelGridRoundSize)3069 void FrameNode::OnPixelRoundFinish(const SizeF& pixelGridRoundSize)
3070 {
3071 CHECK_NULL_VOID(pattern_);
3072 pattern_->OnPixelRoundFinish(pixelGridRoundSize);
3073 }
3074
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)3075 void FrameNode::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
3076 {
3077 pattern_->OnWindowSizeChanged(width, height, type);
3078 }
3079
3080 /* @deprecated This func will be deleted, please use GetTransformRelativeOffset() instead. */
GetOffsetRelativeToWindow() const3081 OffsetF FrameNode::GetOffsetRelativeToWindow() const
3082 {
3083 auto offset = geometryNode_->GetFrameOffset();
3084 auto parent = GetAncestorNodeOfFrame(true);
3085 if (renderContext_ && renderContext_->GetPositionProperty()) {
3086 if (renderContext_->GetPositionProperty()->HasPosition()) {
3087 auto renderPosition =
3088 ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
3089 offset.SetX(static_cast<float>(renderPosition.first));
3090 offset.SetY(static_cast<float>(renderPosition.second));
3091 }
3092 }
3093 while (parent) {
3094 auto parentRenderContext = parent->GetRenderContext();
3095 if (parentRenderContext && parentRenderContext->GetPositionProperty()) {
3096 if (parentRenderContext->GetPositionProperty()->HasPosition()) {
3097 auto parentLayoutProperty = parent->GetLayoutProperty();
3098 CHECK_NULL_RETURN(parentLayoutProperty, offset);
3099 auto parentRenderContextPosition = ContextPositionConvertToPX(
3100 parentRenderContext, parentLayoutProperty->GetLayoutConstraint()->percentReference);
3101 offset.AddX(static_cast<float>(parentRenderContextPosition.first));
3102 offset.AddY(static_cast<float>(parentRenderContextPosition.second));
3103 parent = parent->GetAncestorNodeOfFrame(true);
3104 continue;
3105 }
3106 }
3107 if (parentRenderContext) {
3108 offset += parentRenderContext->GetPaintRectWithoutTransform().GetOffset();
3109 }
3110 parent = parent->GetAncestorNodeOfFrame(true);
3111 }
3112
3113 return offset;
3114 }
3115
GetPositionToScreen()3116 OffsetF FrameNode::GetPositionToScreen()
3117 {
3118 auto offsetCurrent = GetOffsetRelativeToWindow();
3119 auto pipelineContext = GetContext();
3120 CHECK_NULL_RETURN(pipelineContext, OffsetF());
3121 auto windowOffset = pipelineContext->GetCurrentWindowRect().GetOffset();
3122 OffsetF offset(windowOffset.GetX() + offsetCurrent.GetX(), windowOffset.GetY() + offsetCurrent.GetY());
3123 return offset;
3124 }
3125
GetPositionToParentWithTransform() const3126 OffsetF FrameNode::GetPositionToParentWithTransform() const
3127 {
3128 auto context = GetRenderContext();
3129 CHECK_NULL_RETURN(context, OffsetF());
3130 auto offset = context->GetPaintRectWithoutTransform().GetOffset();
3131 PointF pointTmp(offset.GetX(), offset.GetY());
3132 context->GetPointTransformRotate(pointTmp);
3133 offset.SetX(pointTmp.GetX());
3134 offset.SetY(pointTmp.GetY());
3135 return offset;
3136 }
3137
GetPositionToScreenWithTransform()3138 OffsetF FrameNode::GetPositionToScreenWithTransform()
3139 {
3140 auto pipelineContext = GetContext();
3141 CHECK_NULL_RETURN(pipelineContext, OffsetF());
3142 auto windowOffset = pipelineContext->GetCurrentWindowRect().GetOffset();
3143 OffsetF nodeOffset = GetPositionToWindowWithTransform();
3144 OffsetF offset(windowOffset.GetX() + nodeOffset.GetX(), windowOffset.GetY() + nodeOffset.GetY());
3145 return offset;
3146 }
3147
GetPositionToWindowWithTransform(bool fromBottom) const3148 OffsetF FrameNode::GetPositionToWindowWithTransform(bool fromBottom) const
3149 {
3150 auto context = GetRenderContext();
3151 CHECK_NULL_RETURN(context, OffsetF());
3152 auto rect = context->GetPaintRectWithoutTransform();
3153 OffsetF offset;
3154 if (!fromBottom) {
3155 offset = rect.GetOffset();
3156 } else {
3157 OffsetF offsetBottom(rect.GetX() + rect.Width(), rect.GetY() + rect.Height());
3158 offset = offsetBottom;
3159 }
3160 PointF pointNode(offset.GetX(), offset.GetY());
3161 context->GetPointTransformRotate(pointNode);
3162 auto parent = GetAncestorNodeOfFrame(true);
3163 while (parent) {
3164 auto parentRenderContext = parent->GetRenderContext();
3165 offset = parentRenderContext->GetPaintRectWithoutTransform().GetOffset();
3166 PointF pointTmp(offset.GetX() + pointNode.GetX(), offset.GetY() + pointNode.GetY());
3167 parentRenderContext->GetPointTransformRotate(pointTmp);
3168 pointNode.SetX(pointTmp.GetX());
3169 pointNode.SetY(pointTmp.GetY());
3170 parent = parent->GetAncestorNodeOfFrame(true);
3171 }
3172 offset.SetX(pointNode.GetX());
3173 offset.SetY(pointNode.GetY());
3174 return offset;
3175 }
3176
GetTransformRectRelativeToWindow() const3177 RectF FrameNode::GetTransformRectRelativeToWindow() const
3178 {
3179 auto context = GetRenderContext();
3180 CHECK_NULL_RETURN(context, RectF());
3181 RectF rect = context->GetPaintRectWithTransform();
3182 auto parent = GetAncestorNodeOfFrame(true);
3183 while (parent) {
3184 rect = ApplyFrameNodeTranformToRect(rect, parent);
3185 parent = parent->GetAncestorNodeOfFrame(true);
3186 }
3187 return rect;
3188 }
3189
GetTransformRelativeOffset() const3190 OffsetF FrameNode::GetTransformRelativeOffset() const
3191 {
3192 auto context = GetRenderContext();
3193 CHECK_NULL_RETURN(context, OffsetF());
3194 auto offset = context->GetPaintRectWithTransform().GetOffset();
3195 auto parent = GetAncestorNodeOfFrame(true);
3196
3197 while (parent) {
3198 auto parentRenderContext = parent->GetRenderContext();
3199 offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
3200 parent = parent->GetAncestorNodeOfFrame(true);
3201 }
3202
3203 return offset;
3204 }
3205
GetPaintRectOffset(bool excludeSelf) const3206 OffsetF FrameNode::GetPaintRectOffset(bool excludeSelf) const
3207 {
3208 auto context = GetRenderContext();
3209 CHECK_NULL_RETURN(context, OffsetF());
3210 OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithTransform().GetOffset();
3211 auto parent = GetAncestorNodeOfFrame();
3212 while (parent) {
3213 auto renderContext = parent->GetRenderContext();
3214 CHECK_NULL_RETURN(renderContext, OffsetF());
3215 offset += renderContext->GetPaintRectWithTransform().GetOffset();
3216 parent = parent->GetAncestorNodeOfFrame();
3217 }
3218 return offset;
3219 }
3220
GetPaintRectOffsetNG(bool excludeSelf) const3221 OffsetF FrameNode::GetPaintRectOffsetNG(bool excludeSelf) const
3222 {
3223 auto context = GetRenderContext();
3224 CHECK_NULL_RETURN(context, OffsetF());
3225 OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithoutTransform().GetOffset();
3226 Point point = Matrix4::Invert(context->GetRevertMatrix()) * Point(offset.GetX(), offset.GetY());
3227 auto parent = GetAncestorNodeOfFrame();
3228 while (parent) {
3229 auto renderContext = parent->GetRenderContext();
3230 CHECK_NULL_RETURN(renderContext, OffsetF());
3231 auto parentOffset = renderContext->GetPaintRectWithoutTransform().GetOffset();
3232 point = point + Offset(parentOffset.GetX(), parentOffset.GetY());
3233 auto parentMatrix = Matrix4::Invert(renderContext->GetRevertMatrix());
3234 point = parentMatrix * point;
3235 parent = parent->GetAncestorNodeOfFrame();
3236 }
3237 return OffsetF(point.GetX(), point.GetY());
3238 }
3239
GetRectPoints(SizeF & frameSize)3240 std::vector<Point> GetRectPoints(SizeF& frameSize)
3241 {
3242 std::vector<Point> pointList;
3243 pointList.push_back(Point(0, 0));
3244 pointList.push_back(Point(frameSize.Width(), 0));
3245 pointList.push_back(Point(0, frameSize.Height()));
3246 pointList.push_back(Point(frameSize.Width(), frameSize.Height()));
3247 return pointList;
3248 }
3249
GetBoundingBox(std::vector<Point> & pointList)3250 RectF GetBoundingBox(std::vector<Point>& pointList)
3251 {
3252 Point pMax = pointList[0];
3253 Point pMin = pointList[0];
3254
3255 for (auto &point: pointList) {
3256 if (point.GetX() > pMax.GetX()) {
3257 pMax.SetX(point.GetX());
3258 }
3259 if (point.GetX() < pMin.GetX()) {
3260 pMin.SetX(point.GetX());
3261 }
3262 if (point.GetY() > pMax.GetY()) {
3263 pMax.SetY(point.GetY());
3264 }
3265 if (point.GetY() < pMin.GetY()) {
3266 pMin.SetY(point.GetY());
3267 }
3268 }
3269 return RectF(pMin.GetX(), pMin.GetY(), pMax.GetX() - pMin.GetX(), pMax.GetY() - pMin.GetY());
3270 }
3271
GetRectPointToParentWithTransform(std::vector<Point> & pointList,const RefPtr<FrameNode> & parent) const3272 bool FrameNode::GetRectPointToParentWithTransform(std::vector<Point>& pointList, const RefPtr<FrameNode>& parent) const
3273 {
3274 auto renderContext = parent->GetRenderContext();
3275 CHECK_NULL_RETURN(renderContext, false);
3276 auto parentOffset = renderContext->GetPaintRectWithoutTransform().GetOffset();
3277 auto parentMatrix = Matrix4::Invert(renderContext->GetRevertMatrix());
3278 for (auto& point: pointList) {
3279 point = point + Offset(parentOffset.GetX(), parentOffset.GetY());
3280 point = parentMatrix * point;
3281 }
3282 return true;
3283 }
3284
GetPaintRectToWindowWithTransform()3285 RectF FrameNode::GetPaintRectToWindowWithTransform()
3286 {
3287 auto context = GetRenderContext();
3288 CHECK_NULL_RETURN(context, RectF());
3289 auto geometryNode = GetGeometryNode();
3290 CHECK_NULL_RETURN(geometryNode, RectF());
3291 auto frameSize = geometryNode->GetFrameSize();
3292 auto pointList = GetRectPoints(frameSize);
3293 GetRectPointToParentWithTransform(pointList, Claim(this));
3294 auto parent = GetAncestorNodeOfFrame();
3295 while (parent) {
3296 if (GetRectPointToParentWithTransform(pointList, parent)) {
3297 parent = parent->GetAncestorNodeOfFrame();
3298 } else {
3299 return RectF();
3300 }
3301 }
3302 return GetBoundingBox(pointList);
3303 }
3304
GetPaintRectCenter(bool checkWindowBoundary) const3305 OffsetF FrameNode::GetPaintRectCenter(bool checkWindowBoundary) const
3306 {
3307 auto context = GetRenderContext();
3308 CHECK_NULL_RETURN(context, OffsetF());
3309 auto paintRect = context->GetPaintRectWithoutTransform();
3310 auto offset = paintRect.GetOffset();
3311 PointF pointNode(offset.GetX() + paintRect.Width() / 2.0f, offset.GetY() + paintRect.Height() / 2.0f);
3312 context->GetPointTransformRotate(pointNode);
3313 auto parent = GetAncestorNodeOfFrame();
3314 while (parent) {
3315 if (checkWindowBoundary && parent->IsWindowBoundary()) {
3316 break;
3317 }
3318 auto renderContext = parent->GetRenderContext();
3319 CHECK_NULL_RETURN(renderContext, OffsetF());
3320 offset = renderContext->GetPaintRectWithoutTransform().GetOffset();
3321 pointNode.SetX(offset.GetX() + pointNode.GetX());
3322 pointNode.SetY(offset.GetY() + pointNode.GetY());
3323 renderContext->GetPointTransformRotate(pointNode);
3324 parent = parent->GetAncestorNodeOfFrame();
3325 }
3326 return OffsetF(pointNode.GetX(), pointNode.GetY());
3327 }
3328
GetParentGlobalOffsetDuringLayout() const3329 OffsetF FrameNode::GetParentGlobalOffsetDuringLayout() const
3330 {
3331 OffsetF offset {};
3332 auto parent = GetAncestorNodeOfFrame();
3333 while (parent) {
3334 offset += parent->geometryNode_->GetFrameOffset();
3335 parent = parent->GetAncestorNodeOfFrame();
3336 }
3337 return offset;
3338 }
3339
GetPaintRectGlobalOffsetWithTranslate(bool excludeSelf) const3340 std::pair<OffsetF, bool> FrameNode::GetPaintRectGlobalOffsetWithTranslate(bool excludeSelf) const
3341 {
3342 bool error = false;
3343 auto context = GetRenderContext();
3344 CHECK_NULL_RETURN(context, std::make_pair(OffsetF(), error));
3345 OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithTranslate().first.GetOffset();
3346 auto parent = GetAncestorNodeOfFrame();
3347 while (parent) {
3348 auto renderContext = parent->GetRenderContext();
3349 CHECK_NULL_RETURN(renderContext, std::make_pair(OffsetF(), error));
3350 auto [rect, err] = renderContext->GetPaintRectWithTranslate();
3351 error = error || err;
3352 CHECK_NULL_RETURN(rect.IsValid(), std::make_pair(offset + parent->GetPaintRectOffset(), error));
3353 offset += rect.GetOffset();
3354 parent = parent->GetAncestorNodeOfFrame();
3355 }
3356 return std::make_pair(offset, error);
3357 }
3358
GetPaintRectOffsetToPage() const3359 OffsetF FrameNode::GetPaintRectOffsetToPage() const
3360 {
3361 auto context = GetRenderContext();
3362 CHECK_NULL_RETURN(context, OffsetF());
3363 OffsetF offset = context->GetPaintRectWithTransform().GetOffset();
3364 auto parent = GetAncestorNodeOfFrame();
3365 while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
3366 auto renderContext = parent->GetRenderContext();
3367 CHECK_NULL_RETURN(renderContext, OffsetF());
3368 offset += renderContext->GetPaintRectWithTransform().GetOffset();
3369 parent = parent->GetAncestorNodeOfFrame();
3370 }
3371 return (parent && parent->GetTag() == V2::PAGE_ETS_TAG) ? offset : OffsetF();
3372 }
3373
GetViewPort() const3374 std::optional<RectF> FrameNode::GetViewPort() const
3375 {
3376 if (viewPort_.has_value()) {
3377 return viewPort_;
3378 }
3379 auto parent = GetAncestorNodeOfFrame();
3380 while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
3381 auto parentViewPort = parent->GetSelfViewPort();
3382 if (parentViewPort.has_value()) {
3383 return parentViewPort;
3384 }
3385 parent = parent->GetAncestorNodeOfFrame();
3386 }
3387 return std::nullopt;
3388 }
3389
OnNotifyMemoryLevel(int32_t level)3390 void FrameNode::OnNotifyMemoryLevel(int32_t level)
3391 {
3392 pattern_->OnNotifyMemoryLevel(level);
3393 }
3394
GetAllDepthChildrenCount()3395 int32_t FrameNode::GetAllDepthChildrenCount()
3396 {
3397 int32_t result = 0;
3398 std::list<RefPtr<FrameNode>> children;
3399 children.emplace_back(Claim(this));
3400 while (!children.empty()) {
3401 auto& node = children.front();
3402 if (!node->IsInternal()) {
3403 result++;
3404 node->GenerateOneDepthVisibleFrame(children);
3405 }
3406 children.pop_front();
3407 }
3408 return result;
3409 }
3410
OnAccessibilityEvent(AccessibilityEventType eventType,WindowsContentChangeTypes windowsContentChangeType) const3411 void FrameNode::OnAccessibilityEvent(
3412 AccessibilityEventType eventType, WindowsContentChangeTypes windowsContentChangeType) const
3413 {
3414 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3415 AccessibilityEvent event;
3416 event.type = eventType;
3417 event.windowContentChangeTypes = windowsContentChangeType;
3418 event.nodeId = GetAccessibilityId();
3419 auto pipeline = GetContext();
3420 CHECK_NULL_VOID(pipeline);
3421 pipeline->SendEventToAccessibility(event);
3422 }
3423 }
3424
OnAccessibilityEventForVirtualNode(AccessibilityEventType eventType,int64_t accessibilityId)3425 void FrameNode::OnAccessibilityEventForVirtualNode(AccessibilityEventType eventType, int64_t accessibilityId)
3426 {
3427 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3428 AccessibilityEvent event;
3429 event.type = eventType;
3430 event.windowContentChangeTypes = WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID;
3431 event.nodeId = accessibilityId;
3432 auto pipeline = GetContext();
3433 CHECK_NULL_VOID(pipeline);
3434 pipeline->SendEventToAccessibility(event);
3435 }
3436 }
3437
OnAccessibilityEvent(AccessibilityEventType eventType,std::string beforeText,std::string latestContent)3438 void FrameNode::OnAccessibilityEvent(
3439 AccessibilityEventType eventType, std::string beforeText, std::string latestContent)
3440 {
3441 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3442 AccessibilityEvent event;
3443 event.type = eventType;
3444 event.nodeId = GetAccessibilityId();
3445 event.beforeText = beforeText;
3446 event.latestContent = latestContent;
3447 auto pipeline = GetContext();
3448 CHECK_NULL_VOID(pipeline);
3449 pipeline->SendEventToAccessibilityWithNode(event, Claim(this));
3450 }
3451 }
3452
OnAccessibilityEvent(AccessibilityEventType eventType,int64_t stackNodeId,WindowsContentChangeTypes windowsContentChangeType)3453 void FrameNode::OnAccessibilityEvent(
3454 AccessibilityEventType eventType, int64_t stackNodeId, WindowsContentChangeTypes windowsContentChangeType)
3455 {
3456 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3457 AccessibilityEvent event;
3458 event.type = eventType;
3459 event.windowContentChangeTypes = windowsContentChangeType;
3460 event.nodeId = GetAccessibilityId();
3461 event.stackNodeId = stackNodeId;
3462 auto pipeline = GetContext();
3463 CHECK_NULL_VOID(pipeline);
3464 pipeline->SendEventToAccessibility(event);
3465 }
3466 }
3467
OnAccessibilityEvent(AccessibilityEventType eventType,std::string textAnnouncedForAccessibility)3468 void FrameNode::OnAccessibilityEvent(
3469 AccessibilityEventType eventType, std::string textAnnouncedForAccessibility)
3470 {
3471 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3472 if (eventType != AccessibilityEventType::ANNOUNCE_FOR_ACCESSIBILITY) {
3473 return;
3474 }
3475 AccessibilityEvent event;
3476 event.type = eventType;
3477 event.nodeId = GetAccessibilityId();
3478 event.textAnnouncedForAccessibility = textAnnouncedForAccessibility;
3479 auto pipeline = GetContext();
3480 CHECK_NULL_VOID(pipeline);
3481 pipeline->SendEventToAccessibilityWithNode(event, Claim(this));
3482 }
3483 }
3484
OnRecycle()3485 void FrameNode::OnRecycle()
3486 {
3487 for (const auto& destroyCallback : destroyCallbacks_) {
3488 destroyCallback();
3489 }
3490 for (const auto& destroyCallback : destroyCallbacksMap_) {
3491 if (destroyCallback.second) {
3492 destroyCallback.second();
3493 }
3494 }
3495 layoutProperty_->ResetGeometryTransition();
3496 pattern_->OnRecycle();
3497 UINode::OnRecycle();
3498 }
3499
OnReuse()3500 void FrameNode::OnReuse()
3501 {
3502 pattern_->OnReuse();
3503 UINode::OnReuse();
3504 if (SystemProperties::GetDeveloperModeOn()) {
3505 PaintDebugBoundary(SystemProperties::GetDebugBoundaryEnabled());
3506 }
3507 }
3508
MarkRemoving()3509 bool FrameNode::MarkRemoving()
3510 {
3511 bool pendingRemove = false;
3512 if (!layoutProperty_ || !geometryNode_) {
3513 return pendingRemove;
3514 }
3515
3516 isRemoving_ = true;
3517
3518 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
3519 if (geometryTransition != nullptr) {
3520 geometryTransition->Build(WeakClaim(this), false);
3521 pendingRemove = true;
3522 }
3523
3524 const auto children = GetChildren();
3525 for (const auto& child : children) {
3526 pendingRemove = child->MarkRemoving() || pendingRemove;
3527 }
3528 return pendingRemove;
3529 }
3530
AddHotZoneRect(const DimensionRect & hotZoneRect) const3531 void FrameNode::AddHotZoneRect(const DimensionRect& hotZoneRect) const
3532 {
3533 auto gestureHub = GetOrCreateGestureEventHub();
3534 gestureHub->AddResponseRect(hotZoneRect);
3535 }
3536
RemoveLastHotZoneRect() const3537 void FrameNode::RemoveLastHotZoneRect() const
3538 {
3539 auto gestureHub = GetOrCreateGestureEventHub();
3540 gestureHub->RemoveLastResponseRect();
3541 }
3542
OnRemoveFromParent(bool allowTransition)3543 bool FrameNode::OnRemoveFromParent(bool allowTransition)
3544 {
3545 // kick out transition animation if needed, wont re-entry if already detached.
3546 DetachFromMainTree(!allowTransition);
3547 auto context = GetRenderContext();
3548 CHECK_NULL_RETURN(context, false);
3549 if (!allowTransition || RemoveImmediately()) {
3550 // directly remove, reset parent and depth
3551 ResetParent();
3552 return true;
3553 }
3554 // delayed remove, will move self into disappearing children
3555 return false;
3556 }
3557
FindChildByPosition(float x,float y)3558 RefPtr<FrameNode> FrameNode::FindChildByPosition(float x, float y)
3559 {
3560 std::map<int32_t, RefPtr<FrameNode>> hitFrameNodes;
3561 std::list<RefPtr<FrameNode>> children;
3562 GenerateOneDepthAllFrame(children);
3563 for (const auto& child : children) {
3564 if (!child->IsActive()) {
3565 continue;
3566 }
3567 auto geometryNode = child->GetGeometryNode();
3568 if (!geometryNode) {
3569 continue;
3570 }
3571
3572 auto globalFrameRect = geometryNode->GetFrameRect();
3573 globalFrameRect.SetOffset(child->GetOffsetRelativeToWindow());
3574
3575 if (globalFrameRect.IsInRegion(PointF(x, y))) {
3576 hitFrameNodes.insert(std::make_pair(child->GetDepth(), child));
3577 }
3578 }
3579
3580 if (hitFrameNodes.empty()) {
3581 return nullptr;
3582 }
3583
3584 return hitFrameNodes.rbegin()->second;
3585 }
3586
GetAnimatablePropertyFloat(const std::string & propertyName) const3587 RefPtr<NodeAnimatablePropertyBase> FrameNode::GetAnimatablePropertyFloat(const std::string& propertyName) const
3588 {
3589 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3590 if (iter == nodeAnimatablePropertyMap_.end()) {
3591 return nullptr;
3592 }
3593 return iter->second;
3594 }
3595
FindChildByName(const RefPtr<FrameNode> & parentNode,const std::string & nodeName)3596 RefPtr<FrameNode> FrameNode::FindChildByName(const RefPtr<FrameNode>& parentNode, const std::string& nodeName)
3597 {
3598 CHECK_NULL_RETURN(parentNode, nullptr);
3599 const auto& children = parentNode->GetChildren();
3600 for (const auto& child : children) {
3601 auto childFrameNode = AceType::DynamicCast<FrameNode>(child);
3602 if (childFrameNode && childFrameNode->GetInspectorId().value_or("") == nodeName) {
3603 return childFrameNode;
3604 }
3605 auto childFindResult = FindChildByName(childFrameNode, nodeName);
3606 if (childFindResult) {
3607 return childFindResult;
3608 }
3609 }
3610 return nullptr;
3611 }
3612
CreateAnimatablePropertyFloat(const std::string & propertyName,float value,const std::function<void (float)> & onCallbackEvent,const PropertyUnit & propertyType)3613 void FrameNode::CreateAnimatablePropertyFloat(const std::string& propertyName, float value,
3614 const std::function<void(float)>& onCallbackEvent, const PropertyUnit& propertyType)
3615 {
3616 auto context = GetRenderContext();
3617 CHECK_NULL_VOID(context);
3618 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3619 if (iter != nodeAnimatablePropertyMap_.end()) {
3620 return;
3621 }
3622 auto property = AceType::MakeRefPtr<NodeAnimatablePropertyFloat>(value, std::move(onCallbackEvent));
3623 context->AttachNodeAnimatableProperty(property);
3624 if (propertyType == PropertyUnit::PIXEL_POSITION) {
3625 property->SetPropertyUnit(propertyType);
3626 }
3627 nodeAnimatablePropertyMap_.emplace(propertyName, property);
3628 }
3629
DeleteAnimatablePropertyFloat(const std::string & propertyName)3630 void FrameNode::DeleteAnimatablePropertyFloat(const std::string& propertyName)
3631 {
3632 auto context = GetRenderContext();
3633 CHECK_NULL_VOID(context);
3634 RefPtr<NodeAnimatablePropertyBase> propertyRef = GetAnimatablePropertyFloat(propertyName);
3635 if (propertyRef) {
3636 context->DetachNodeAnimatableProperty(propertyRef);
3637 nodeAnimatablePropertyMap_.erase(propertyName);
3638 }
3639 }
3640
UpdateAnimatablePropertyFloat(const std::string & propertyName,float value)3641 void FrameNode::UpdateAnimatablePropertyFloat(const std::string& propertyName, float value)
3642 {
3643 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3644 if (iter == nodeAnimatablePropertyMap_.end()) {
3645 return;
3646 }
3647 auto property = AceType::DynamicCast<NodeAnimatablePropertyFloat>(iter->second);
3648 CHECK_NULL_VOID(property);
3649 property->Set(value);
3650 if (AnimationUtils::IsImplicitAnimationOpen()) {
3651 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_START_ANIMATION);
3652 }
3653 }
3654
CreateAnimatableArithmeticProperty(const std::string & propertyName,RefPtr<CustomAnimatableArithmetic> & value,std::function<void (const RefPtr<CustomAnimatableArithmetic> &)> & onCallbackEvent)3655 void FrameNode::CreateAnimatableArithmeticProperty(const std::string& propertyName,
3656 RefPtr<CustomAnimatableArithmetic>& value,
3657 std::function<void(const RefPtr<CustomAnimatableArithmetic>&)>& onCallbackEvent)
3658 {
3659 auto context = GetRenderContext();
3660 CHECK_NULL_VOID(context);
3661 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3662 if (iter != nodeAnimatablePropertyMap_.end()) {
3663 return;
3664 }
3665 auto property = AceType::MakeRefPtr<NodeAnimatableArithmeticProperty>(value, std::move(onCallbackEvent));
3666 context->AttachNodeAnimatableProperty(property);
3667 nodeAnimatablePropertyMap_.emplace(propertyName, property);
3668 }
3669
UpdateAnimatableArithmeticProperty(const std::string & propertyName,RefPtr<CustomAnimatableArithmetic> & value)3670 void FrameNode::UpdateAnimatableArithmeticProperty(
3671 const std::string& propertyName, RefPtr<CustomAnimatableArithmetic>& value)
3672 {
3673 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3674 if (iter == nodeAnimatablePropertyMap_.end()) {
3675 return;
3676 }
3677 auto property = AceType::DynamicCast<NodeAnimatableArithmeticProperty>(iter->second);
3678 CHECK_NULL_VOID(property);
3679 property->Set(value);
3680 }
3681
ProvideRestoreInfo()3682 std::string FrameNode::ProvideRestoreInfo()
3683 {
3684 return pattern_->ProvideRestoreInfo();
3685 }
3686
RemoveImmediately() const3687 bool FrameNode::RemoveImmediately() const
3688 {
3689 auto context = GetRenderContext();
3690 CHECK_NULL_RETURN(context, true);
3691 // has transition out animation, need to wait for animation end
3692 return !context->HasTransitionOutAnimation();
3693 }
3694
GetNodesById(const std::unordered_set<int32_t> & set)3695 std::vector<RefPtr<FrameNode>> FrameNode::GetNodesById(const std::unordered_set<int32_t>& set)
3696 {
3697 std::vector<RefPtr<FrameNode>> nodes;
3698 for (auto nodeId : set) {
3699 auto uiNode = ElementRegister::GetInstance()->GetUINodeById(nodeId);
3700 if (!uiNode) {
3701 continue;
3702 }
3703 auto frameNode = DynamicCast<FrameNode>(uiNode);
3704 if (frameNode) {
3705 nodes.emplace_back(frameNode);
3706 }
3707 }
3708 return nodes;
3709 }
3710
GetNodesPtrById(const std::unordered_set<int32_t> & set)3711 std::vector<FrameNode*> FrameNode::GetNodesPtrById(const std::unordered_set<int32_t>& set)
3712 {
3713 std::vector<FrameNode*> nodes;
3714 for (auto nodeId : set) {
3715 NG::FrameNode* frameNode = ElementRegister::GetInstance()->GetFrameNodePtrById(nodeId);
3716 if (!frameNode) {
3717 continue;
3718 }
3719 nodes.emplace_back(frameNode);
3720 }
3721 return nodes;
3722 }
3723
GetPreviewScaleVal() const3724 double FrameNode::GetPreviewScaleVal() const
3725 {
3726 double scale = 1.0;
3727 auto maxWidth = DragDropManager::GetMaxWidthBaseOnGridSystem(GetContextRefPtr());
3728 auto geometryNode = GetGeometryNode();
3729 CHECK_NULL_RETURN(geometryNode, scale);
3730 auto width = geometryNode->GetFrameRect().Width();
3731 if (GetTag() != V2::WEB_ETS_TAG && width != 0 && width > maxWidth && previewOption_.isScaleEnabled) {
3732 scale = maxWidth / width;
3733 }
3734 return scale;
3735 }
3736
IsPreviewNeedScale() const3737 bool FrameNode::IsPreviewNeedScale() const
3738 {
3739 return GetPreviewScaleVal() < 1.0f;
3740 }
3741
GetNodeExpectedRate()3742 int32_t FrameNode::GetNodeExpectedRate()
3743 {
3744 if (sceneRateMap_.empty()) {
3745 return 0;
3746 }
3747 auto iter = std::max_element(
3748 sceneRateMap_.begin(), sceneRateMap_.end(), [](auto a, auto b) { return a.second < b.second; });
3749 return iter->second;
3750 }
3751
AddFRCSceneInfo(const std::string & scene,float speed,SceneStatus status)3752 void FrameNode::AddFRCSceneInfo(const std::string& scene, float speed, SceneStatus status)
3753 {
3754 if (SystemProperties::GetDebugEnabled()) {
3755 const std::string sceneStatusStrs[] = { "START", "RUNNING", "END" };
3756 LOGD("%{public}s AddFRCSceneInfo scene:%{public}s speed:%{public}f status:%{public}s", GetTag().c_str(),
3757 scene.c_str(), std::abs(speed), sceneStatusStrs[static_cast<int32_t>(status)].c_str());
3758 }
3759
3760 auto renderContext = GetRenderContext();
3761 CHECK_NULL_VOID(renderContext);
3762 auto pipelineContext = GetContext();
3763 CHECK_NULL_VOID(pipelineContext);
3764 auto frameRateManager = pipelineContext->GetFrameRateManager();
3765 CHECK_NULL_VOID(frameRateManager);
3766
3767 auto expectedRate = renderContext->CalcExpectedFrameRate(scene, std::abs(speed));
3768 auto nodeId = GetId();
3769 auto iter = sceneRateMap_.find(scene);
3770 switch (status) {
3771 case SceneStatus::START: {
3772 if (iter == sceneRateMap_.end()) {
3773 if (sceneRateMap_.empty()) {
3774 frameRateManager->AddNodeRate(nodeId);
3775 }
3776 sceneRateMap_.emplace(scene, expectedRate);
3777 frameRateManager->UpdateNodeRate(nodeId, GetNodeExpectedRate());
3778 }
3779 return;
3780 }
3781 case SceneStatus::RUNNING: {
3782 if (iter != sceneRateMap_.end() && iter->second != expectedRate) {
3783 iter->second = expectedRate;
3784 auto nodeExpectedRate = GetNodeExpectedRate();
3785 frameRateManager->UpdateNodeRate(nodeId, nodeExpectedRate);
3786 }
3787 return;
3788 }
3789 case SceneStatus::END: {
3790 if (iter != sceneRateMap_.end()) {
3791 sceneRateMap_.erase(iter);
3792 if (sceneRateMap_.empty()) {
3793 frameRateManager->RemoveNodeRate(nodeId);
3794 } else {
3795 auto nodeExpectedRate = GetNodeExpectedRate();
3796 frameRateManager->UpdateNodeRate(nodeId, nodeExpectedRate);
3797 }
3798 }
3799 return;
3800 }
3801 default:
3802 return;
3803 }
3804 }
3805
GetPercentSensitive()3806 void FrameNode::GetPercentSensitive()
3807 {
3808 auto res = layoutProperty_->GetPercentSensitive();
3809 if (res.first) {
3810 if (layoutAlgorithm_) {
3811 layoutAlgorithm_->SetPercentWidth(true);
3812 }
3813 }
3814 if (res.second) {
3815 if (layoutAlgorithm_) {
3816 layoutAlgorithm_->SetPercentHeight(true);
3817 }
3818 }
3819 }
3820
UpdatePercentSensitive()3821 void FrameNode::UpdatePercentSensitive()
3822 {
3823 bool percentHeight = layoutAlgorithm_ ? layoutAlgorithm_->GetPercentHeight() : true;
3824 bool percentWidth = layoutAlgorithm_ ? layoutAlgorithm_->GetPercentWidth() : true;
3825 auto res = layoutProperty_->UpdatePercentSensitive(percentHeight, percentWidth);
3826 if (res.first) {
3827 auto parent = GetAncestorNodeOfFrame();
3828 if (parent && parent->layoutAlgorithm_) {
3829 parent->layoutAlgorithm_->SetPercentWidth(true);
3830 }
3831 }
3832 if (res.second) {
3833 auto parent = GetAncestorNodeOfFrame();
3834 if (parent && parent->layoutAlgorithm_) {
3835 parent->layoutAlgorithm_->SetPercentHeight(true);
3836 }
3837 }
3838 }
3839
3840 // This will call child and self measure process.
Measure(const std::optional<LayoutConstraintF> & parentConstraint)3841 void FrameNode::Measure(const std::optional<LayoutConstraintF>& parentConstraint)
3842 {
3843 ACE_LAYOUT_TRACE_BEGIN("Measure[%s][self:%d][parent:%d][key:%s]", GetTag().c_str(), GetId(),
3844 GetAncestorNodeOfFrame() ? GetAncestorNodeOfFrame()->GetId() : 0, GetInspectorIdValue("").c_str());
3845 ArkUIPerfMonitor::GetInstance().RecordLayoutNode();
3846 isLayoutComplete_ = false;
3847 if (!oldGeometryNode_) {
3848 oldGeometryNode_ = geometryNode_->Clone();
3849 }
3850 pattern_->BeforeCreateLayoutWrapper();
3851 GetLayoutAlgorithm(true);
3852
3853 if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
3854 layoutAlgorithm_->SetSkipMeasure();
3855 layoutAlgorithm_->SetSkipLayout();
3856 geometryNode_->SetFrameSize(SizeF());
3857 geometryNode_->UpdateMargin(MarginPropertyF());
3858 isLayoutDirtyMarked_ = false;
3859 ACE_LAYOUT_TRACE_END()
3860 return;
3861 }
3862 if (!isActive_) {
3863 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
3864 }
3865
3866 if (layoutAlgorithm_->SkipMeasure()) {
3867 isLayoutDirtyMarked_ = false;
3868 ACE_LAYOUT_TRACE_END()
3869 return;
3870 }
3871
3872 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
3873 if (geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this))) {
3874 geometryTransition->WillLayout(Claim(this));
3875 }
3876 auto preConstraint = layoutProperty_->GetLayoutConstraint();
3877 auto contentConstraint = layoutProperty_->GetContentLayoutConstraint();
3878 layoutProperty_->BuildGridProperty(Claim(this));
3879
3880 if (layoutProperty_->GetLayoutRect()) {
3881 layoutProperty_->UpdateLayoutConstraintWithLayoutRect();
3882 } else if (parentConstraint) {
3883 ApplyConstraint(*parentConstraint);
3884 } else {
3885 CreateRootConstraint();
3886 }
3887
3888 layoutProperty_->UpdateContentConstraint();
3889 geometryNode_->UpdateMargin(layoutProperty_->CreateMargin());
3890 geometryNode_->UpdatePaddingWithBorder(layoutProperty_->CreatePaddingAndBorder());
3891
3892 isConstraintNotChanged_ = layoutProperty_->ConstraintEqual(preConstraint, contentConstraint);
3893
3894 isLayoutDirtyMarked_ = false;
3895
3896 if (isConstraintNotChanged_) {
3897 if (!CheckNeedForceMeasureAndLayout()) {
3898 ACE_SCOPED_TRACE("SkipMeasure [%s][self:%d]", GetTag().c_str(), GetId());
3899 layoutAlgorithm_->SetSkipMeasure();
3900 ACE_LAYOUT_TRACE_END()
3901 return;
3902 }
3903 } else {
3904 contentConstraintChanges_.UpdateFlags(contentConstraint, layoutProperty_->GetContentLayoutConstraint());
3905 constraintChanges_.UpdateFlags(preConstraint, layoutProperty_->GetLayoutConstraint());
3906 }
3907
3908 GetPercentSensitive();
3909
3910 if (extensionHandler_ && !extensionHandler_->HasDrawModifier()) {
3911 auto extensionLayoutConstraint =
3912 ExtensionLayoutConstraint::Create(GetLayoutProperty()->GetLayoutConstraint().value());
3913 extensionHandler_->SetInnerMeasureImpl([this](const ExtensionLayoutConstraint&) {
3914 auto size = layoutAlgorithm_->MeasureContent(layoutProperty_->CreateContentConstraint(), this);
3915 if (size.has_value()) {
3916 geometryNode_->SetContentSize(size.value());
3917 }
3918 layoutAlgorithm_->Measure(this);
3919 });
3920 extensionHandler_->Measure(extensionLayoutConstraint);
3921 } else {
3922 auto size = layoutAlgorithm_->MeasureContent(layoutProperty_->CreateContentConstraint(), this);
3923 if (size.has_value()) {
3924 geometryNode_->SetContentSize(size.value());
3925 }
3926 layoutAlgorithm_->Measure(this);
3927 }
3928
3929 if (overlayNode_) {
3930 overlayNode_->Measure(layoutProperty_->CreateChildConstraint());
3931 }
3932 UpdatePercentSensitive();
3933 // check aspect radio.
3934 if (pattern_ && pattern_->IsNeedAdjustByAspectRatio() && !layoutProperty_->GetLayoutRect()) {
3935 const auto& magicItemProperty = layoutProperty_->GetMagicItemProperty();
3936 auto aspectRatio = magicItemProperty.GetAspectRatioValue();
3937 // Adjust by aspect ratio, firstly pick height based on width. It means that when width, height and
3938 // aspectRatio are all set, the height is not used.
3939 auto width = geometryNode_->GetFrameSize().Width();
3940 auto height = width / aspectRatio;
3941 geometryNode_->SetFrameSize(SizeF({ width, height }));
3942 }
3943
3944 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
3945 ACE_LAYOUT_TRACE_END()
3946 }
3947
3948 // Called to perform layout children.
Layout()3949 void FrameNode::Layout()
3950 {
3951 ACE_LAYOUT_TRACE_BEGIN("Layout[%s][self:%d][parent:%d][key:%s]", GetTag().c_str(), GetId(),
3952 GetAncestorNodeOfFrame() ? GetAncestorNodeOfFrame()->GetId() : 0, GetInspectorIdValue("").c_str());
3953 if (layoutProperty_->GetLayoutRect()) {
3954 GetGeometryNode()->SetFrameOffset(layoutProperty_->GetLayoutRect().value().GetOffset());
3955 }
3956 int64_t time = GetSysTimestamp();
3957 OffsetNodeToSafeArea();
3958 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
3959 if (geometryTransition != nullptr) {
3960 if (geometryTransition->IsNodeInAndActive(Claim(this))) {
3961 if (IsRootMeasureNode()) {
3962 UINode::SetGeometryTransitionInRecursive(true);
3963 } else {
3964 SetSkipSyncGeometryNode();
3965 }
3966 }
3967 }
3968 if (CheckNeedLayout(layoutProperty_->GetPropertyChangeFlag())) {
3969 if (!layoutProperty_->GetLayoutConstraint()) {
3970 const auto& parentLayoutConstraint = geometryNode_->GetParentLayoutConstraint();
3971 if (layoutProperty_->GetLayoutRect()) {
3972 layoutProperty_->UpdateLayoutConstraintWithLayoutRect();
3973 } else if (parentLayoutConstraint) {
3974 layoutProperty_->UpdateLayoutConstraint(parentLayoutConstraint.value());
3975 } else {
3976 LayoutConstraintF layoutConstraint;
3977 layoutConstraint.percentReference.SetWidth(PipelineContext::GetCurrentRootWidth());
3978 layoutConstraint.percentReference.SetHeight(PipelineContext::GetCurrentRootHeight());
3979 layoutProperty_->UpdateLayoutConstraint(layoutConstraint);
3980 }
3981 layoutProperty_->UpdateContentConstraint();
3982 }
3983
3984 if (extensionHandler_ && !extensionHandler_->HasDrawModifier()) {
3985 extensionHandler_->SetInnerLayoutImpl(
3986 [this](int32_t, int32_t, int32_t, int32_t) { GetLayoutAlgorithm()->Layout(this); });
3987 const auto& rect = geometryNode_->GetFrameRect();
3988 extensionHandler_->Layout(rect.Width(), rect.Height(), rect.GetX(), rect.GetY());
3989 } else {
3990 GetLayoutAlgorithm()->Layout(this);
3991 }
3992
3993 if (overlayNode_) {
3994 LayoutOverlay();
3995 }
3996 time = GetSysTimestamp() - time;
3997 AddNodeFlexLayouts();
3998 AddNodeLayoutTime(time);
3999 } else {
4000 GetLayoutAlgorithm()->SetSkipLayout();
4001 }
4002
4003 auto pipeline = GetContext();
4004 CHECK_NULL_VOID_LAYOUT_TRACE_END(pipeline);
4005 auto stageManager = pipeline->GetStageManager();
4006 CHECK_NULL_VOID(stageManager);
4007 bool isFocusOnPage = stageManager->CheckPageFocus();
4008 bool needSyncRsNode = false;
4009 DirtySwapConfig config;
4010 bool willSyncGeoProperties = OnLayoutFinish(needSyncRsNode, config);
4011 needSyncRsNode |= AvoidKeyboard(isFocusOnPage);
4012 if (GetIsGeometryTransitionIn()) {
4013 renderContext_->SetFrameWithoutAnimation(renderContext_->GetPaintRectWithoutTransform());
4014 SetIsGeometryTransitionIn(false);
4015 }
4016 // skip wrapping task if node will not sync
4017 CHECK_NULL_VOID_LAYOUT_TRACE_END(willSyncGeoProperties);
4018 auto task = [weak = WeakClaim(this), needSync = needSyncRsNode, dirtyConfig = config]() {
4019 auto frameNode = weak.Upgrade();
4020 CHECK_NULL_VOID(frameNode);
4021 frameNode->SyncGeometryNode(needSync, dirtyConfig);
4022 };
4023 pipeline->AddSyncGeometryNodeTask(task);
4024 if (SelfOrParentExpansive()) {
4025 auto pipeline = GetContext();
4026 CHECK_NULL_VOID_LAYOUT_TRACE_END(pipeline);
4027 auto safeAreaManager = pipeline->GetSafeAreaManager();
4028 CHECK_NULL_VOID_LAYOUT_TRACE_END(safeAreaManager);
4029 safeAreaManager->AddNeedExpandNode(GetHostNode());
4030 }
4031 // if a node has geo transition but not the root node, add task only but not flush
4032 // or add to expand list, self node will be added to expand list in next layout
4033 if (geometryTransition != nullptr && !IsRootMeasureNode()) {
4034 ACE_LAYOUT_TRACE_END()
4035 return;
4036 }
4037 if (geometryTransition != nullptr) {
4038 pipeline->FlushSyncGeometryNodeTasks();
4039 }
4040 ACE_LAYOUT_TRACE_END()
4041 }
4042
SelfExpansive()4043 bool FrameNode::SelfExpansive()
4044 {
4045 auto&& opts = GetLayoutProperty()->GetSafeAreaExpandOpts();
4046 return opts && (opts->Expansive() || opts->switchToNone);
4047 }
4048
SelfExpansiveToKeyboard()4049 bool FrameNode::SelfExpansiveToKeyboard()
4050 {
4051 auto&& opts = GetLayoutProperty()->GetSafeAreaExpandOpts();
4052 return opts && opts->ExpansiveToKeyboard();
4053 }
4054
ParentExpansive()4055 bool FrameNode::ParentExpansive()
4056 {
4057 auto parent = GetAncestorNodeOfFrame();
4058 CHECK_NULL_RETURN(parent, false);
4059 auto parentLayoutProperty = parent->GetLayoutProperty();
4060 CHECK_NULL_RETURN(parentLayoutProperty, false);
4061 auto&& parentOpts = parentLayoutProperty->GetSafeAreaExpandOpts();
4062 return parentOpts && parentOpts->Expansive();
4063 }
4064
UpdateFocusState()4065 void FrameNode::UpdateFocusState()
4066 {
4067 auto focusHub = GetFocusHub();
4068 if (focusHub && focusHub->IsCurrentFocus()) {
4069 focusHub->ClearFocusState();
4070 focusHub->PaintFocusState();
4071 }
4072 }
4073
SelfOrParentExpansive()4074 bool FrameNode::SelfOrParentExpansive()
4075 {
4076 return SelfExpansive() || ParentExpansive();
4077 }
4078
ProcessAccessibilityVirtualNode()4079 void FrameNode::ProcessAccessibilityVirtualNode()
4080 {
4081 if (!hasAccessibilityVirtualNode_) {
4082 return;
4083 }
4084 auto accessibilityProperty = GetAccessibilityProperty<AccessibilityProperty>();
4085 auto virtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
4086 auto virtualFrameNode = AceType::DynamicCast<NG::FrameNode>(virtualNode);
4087 if (virtualFrameNode) {
4088 auto constraint = GetLayoutConstraint();
4089 virtualFrameNode->ApplyConstraint(constraint);
4090 ProcessOffscreenNode(virtualFrameNode);
4091 }
4092 }
4093
UpdateAccessibilityNodeRect()4094 void FrameNode::UpdateAccessibilityNodeRect()
4095 {
4096 auto accessibilityProperty = GetAccessibilityProperty<AccessibilityProperty>();
4097 CHECK_NULL_VOID(accessibilityProperty);
4098 auto isFocus = accessibilityProperty->GetAccessibilityFocusState();
4099 if (isFocus && !IsAccessibilityVirtualNode()) {
4100 renderContext_->UpdateAccessibilityRoundRect();
4101 }
4102 }
4103
OnLayoutFinish(bool & needSyncRsNode,DirtySwapConfig & config)4104 bool FrameNode::OnLayoutFinish(bool& needSyncRsNode, DirtySwapConfig& config)
4105 {
4106 auto context = GetContext();
4107 if (isLayoutNode_ && context) {
4108 context->AddLayoutNode(Claim(this));
4109 }
4110 isLayoutComplete_ = true;
4111 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
4112 bool hasTransition = geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this));
4113 if (!isActive_ && !hasTransition) {
4114 layoutAlgorithm_.Reset();
4115 return false;
4116 }
4117 if (needSkipSyncGeometryNode_ && (!geometryTransition || !geometryTransition->IsNodeInAndActive(Claim(this)))) {
4118 layoutAlgorithm_.Reset();
4119 return false;
4120 }
4121 // update layout size.
4122 bool frameSizeChange = true;
4123 bool frameOffsetChange = true;
4124 bool contentSizeChange = true;
4125 bool contentOffsetChange = true;
4126 if (oldGeometryNode_) {
4127 frameSizeChange = geometryNode_->GetFrameSize() != oldGeometryNode_->GetFrameSize();
4128 frameOffsetChange = geometryNode_->GetFrameOffset() != oldGeometryNode_->GetFrameOffset();
4129 contentSizeChange = geometryNode_->GetContentSize() != oldGeometryNode_->GetContentSize();
4130 contentOffsetChange = geometryNode_->GetContentOffset() != oldGeometryNode_->GetContentOffset();
4131 oldGeometryNode_.Reset();
4132 }
4133
4134 // clean layout flag.
4135 layoutProperty_->CleanDirty();
4136 needSyncRsNode = frameSizeChange || frameOffsetChange ||
4137 (pattern_->GetContextParam().has_value() && contentSizeChange) || HasPositionProp() ||
4138 SelfOrParentExpansive();
4139 if (hasTransition) {
4140 geometryTransition->DidLayout(Claim(this));
4141 if (geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
4142 isLayoutDirtyMarked_ = true;
4143 }
4144 needSyncRsNode = false;
4145 }
4146 if (GetTag() != V2::PAGE_ETS_TAG) {
4147 renderContext_->SavePaintRect(true, layoutProperty_->GetPixelRound());
4148 if (needSyncRsNode) {
4149 renderContext_->SyncPartialRsProperties();
4150 }
4151 }
4152 config = { .frameSizeChange = frameSizeChange,
4153 .frameOffsetChange = frameOffsetChange,
4154 .contentSizeChange = contentSizeChange,
4155 .contentOffsetChange = contentOffsetChange };
4156 // check if need to paint content.
4157 auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(layoutAlgorithm_);
4158 CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
4159 config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure();
4160 config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
4161 if (!config.skipMeasure && !config.skipLayout && GetInspectorId()) {
4162 auto pipeline = PipelineContext::GetCurrentContext();
4163 CHECK_NULL_RETURN(pipeline, false);
4164 pipeline->OnLayoutCompleted(GetInspectorId()->c_str());
4165 }
4166 auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config);
4167 needRerender =
4168 needRerender || pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config.skipMeasure, config.skipLayout);
4169 if (needRerender || (extensionHandler_ && extensionHandler_->NeedRender()) ||
4170 CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
4171 MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
4172 }
4173 layoutAlgorithm_.Reset();
4174 UpdateAccessibilityNodeRect();
4175 ProcessAccessibilityVirtualNode();
4176 auto pipeline = GetContext();
4177 CHECK_NULL_RETURN(pipeline, false);
4178 pipeline->SendUpdateVirtualNodeFocusEvent();
4179 return true;
4180 }
4181
SyncGeometryNode(bool needSyncRsNode,const DirtySwapConfig & config)4182 void FrameNode::SyncGeometryNode(bool needSyncRsNode, const DirtySwapConfig& config)
4183 {
4184 if (SystemProperties::GetSyncDebugTraceEnabled()) {
4185 ACE_LAYOUT_TRACE_BEGIN("SyncGeometryNode[%s][self:%d][parent:%d][key:%s]", GetTag().c_str(), GetId(),
4186 GetParent() ? GetParent()->GetId() : 0, GetInspectorIdValue("").c_str());
4187 ACE_LAYOUT_TRACE_END()
4188 }
4189
4190 // update border.
4191 if (layoutProperty_->GetBorderWidthProperty()) {
4192 if (!renderContext_->HasBorderColor()) {
4193 BorderColorProperty borderColorProperty;
4194 borderColorProperty.SetColor(Color::BLACK);
4195 renderContext_->UpdateBorderColor(borderColorProperty);
4196 }
4197 if (!renderContext_->HasBorderStyle()) {
4198 BorderStyleProperty borderStyleProperty;
4199 borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
4200 renderContext_->UpdateBorderStyle(borderStyleProperty);
4201 }
4202 if (!renderContext_->HasDashGap()) {
4203 BorderWidthProperty dashGapProperty;
4204 dashGapProperty.SetBorderWidth(Dimension(-1));
4205 renderContext_->UpdateDashGap(dashGapProperty);
4206 }
4207 if (!renderContext_->HasDashWidth()) {
4208 BorderWidthProperty dashWidthProperty;
4209 dashWidthProperty.SetBorderWidth(Dimension(-1));
4210 renderContext_->UpdateDashWidth(dashWidthProperty);
4211 }
4212 if (layoutProperty_->GetLayoutConstraint().has_value()) {
4213 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
4214 ScaleProperty::CreateScaleProperty(),
4215 layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
4216 } else {
4217 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
4218 ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
4219 }
4220 }
4221
4222 pattern_->OnSyncGeometryNode(config);
4223 if (needSyncRsNode) {
4224 pattern_->BeforeSyncGeometryProperties(config);
4225 renderContext_->SyncGeometryProperties(RawPtr(geometryNode_), true, layoutProperty_->GetPixelRound());
4226 TriggerOnSizeChangeCallback();
4227 }
4228
4229 // update background
4230 if (builderFunc_) {
4231 auto builderNode = builderFunc_();
4232 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
4233 AceType::MakeRefPtr<LinearLayoutPattern>(true));
4234 if (builderNode) {
4235 builderNode->MountToParent(columnNode);
4236 }
4237 SetBackgroundLayoutConstraint(columnNode);
4238 renderContext_->CreateBackgroundPixelMap(columnNode);
4239 builderFunc_ = nullptr;
4240 backgroundNode_ = columnNode;
4241 }
4242
4243 // update focus state
4244 UpdateFocusState();
4245
4246 // rebuild child render node.
4247 if (!isLayoutNode_) {
4248 RebuildRenderContextTree();
4249 }
4250
4251 /* Adjust components' position which have been set grid properties */
4252 AdjustGridOffset();
4253 }
4254
GetOrCreateChildByIndex(uint32_t index,bool addToRenderTree,bool isCache)4255 RefPtr<LayoutWrapper> FrameNode::GetOrCreateChildByIndex(uint32_t index, bool addToRenderTree, bool isCache)
4256 {
4257 auto child = frameProxy_->GetFrameNodeByIndex(index, true, isCache, addToRenderTree);
4258 if (child) {
4259 child->SetSkipSyncGeometryNode(SkipSyncGeometryNode());
4260 if (addToRenderTree) {
4261 child->SetActive(true);
4262 }
4263 }
4264 return child;
4265 }
4266
GetChildByIndex(uint32_t index,bool isCache)4267 RefPtr<LayoutWrapper> FrameNode::GetChildByIndex(uint32_t index, bool isCache)
4268 {
4269 return frameProxy_->GetFrameNodeByIndex(index, false, isCache, false);
4270 }
4271
GetFrameNodeChildByIndex(uint32_t index,bool isCache,bool isExpand)4272 FrameNode* FrameNode::GetFrameNodeChildByIndex(uint32_t index, bool isCache, bool isExpand)
4273 {
4274 auto frameNode = isExpand ? DynamicCast<FrameNode>(frameProxy_->GetFrameNodeByIndex(index, true, isCache, false))
4275 : DynamicCast<FrameNode>(UINode::GetFrameChildByIndexWithoutExpanded(index));
4276 return RawPtr(frameNode);
4277 }
4278
GetChildTrueIndex(const RefPtr<LayoutWrapper> & child) const4279 int32_t FrameNode::GetChildTrueIndex(const RefPtr<LayoutWrapper>& child) const
4280 {
4281 return frameProxy_->GetChildIndex(child);
4282 }
4283
GetChildTrueTotalCount() const4284 uint32_t FrameNode::GetChildTrueTotalCount() const
4285 {
4286 return frameProxy_->GetTotalCount();
4287 }
4288
GetAllChildrenWithBuild(bool addToRenderTree)4289 ChildrenListWithGuard FrameNode::GetAllChildrenWithBuild(bool addToRenderTree)
4290 {
4291 const auto& children = frameProxy_->GetAllFrameChildren();
4292 {
4293 auto guard = frameProxy_->GetGuard();
4294 for (const auto& child : children) {
4295 if (addToRenderTree) {
4296 child->SetActive(true);
4297 }
4298 child->SetSkipSyncGeometryNode(SkipSyncGeometryNode());
4299 }
4300 }
4301 return children;
4302 }
4303
RemoveAllChildInRenderTree()4304 void FrameNode::RemoveAllChildInRenderTree()
4305 {
4306 frameProxy_->RemoveAllChildInRenderTree();
4307 }
4308
SetActiveChildRange(int32_t start,int32_t end,int32_t cacheStart,int32_t cacheEnd)4309 void FrameNode::SetActiveChildRange(int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd)
4310 {
4311 frameProxy_->SetActiveChildRange(start, end, cacheStart, cacheEnd);
4312 }
4313
SetActiveChildRange(const std::optional<ActiveChildSets> & activeChildSets,const std::optional<ActiveChildRange> & activeChildRange)4314 void FrameNode::SetActiveChildRange(
4315 const std::optional<ActiveChildSets>& activeChildSets, const std::optional<ActiveChildRange>& activeChildRange)
4316 {
4317 frameProxy_->SetActiveChildRange(activeChildSets, activeChildRange);
4318 }
4319
RecycleItemsByIndex(int32_t start,int32_t end)4320 void FrameNode::RecycleItemsByIndex(int32_t start, int32_t end)
4321 {
4322 frameProxy_->RecycleItemsByIndex(start, end);
4323 }
4324
RemoveChildInRenderTree(uint32_t index)4325 void FrameNode::RemoveChildInRenderTree(uint32_t index)
4326 {
4327 frameProxy_->RemoveChildInRenderTree(index);
4328 }
4329
SkipMeasureContent() const4330 bool FrameNode::SkipMeasureContent() const
4331 {
4332 return layoutAlgorithm_->SkipMeasure();
4333 }
4334
CheckNeedForceMeasureAndLayout()4335 bool FrameNode::CheckNeedForceMeasureAndLayout()
4336 {
4337 PropertyChangeFlag flag = layoutProperty_->GetPropertyChangeFlag();
4338 return CheckNeedMeasure(flag) || CheckNeedLayout(flag);
4339 }
4340
GetOffsetInScreen()4341 OffsetF FrameNode::GetOffsetInScreen()
4342 {
4343 auto frameOffset = GetPaintRectOffset();
4344 auto pipelineContext = PipelineContext::GetCurrentContext();
4345 CHECK_NULL_RETURN(pipelineContext, OffsetF(0.0f, 0.0f));
4346 auto window = pipelineContext->GetWindow();
4347 CHECK_NULL_RETURN(window, OffsetF(0.0f, 0.0f));
4348 auto windowOffset = window->GetCurrentWindowRect().GetOffset();
4349 frameOffset += OffsetT<float> { windowOffset.GetX(), windowOffset.GetY() };
4350 return frameOffset;
4351 }
4352
GetOffsetInSubwindow(const OffsetF & subwindowOffset)4353 OffsetF FrameNode::GetOffsetInSubwindow(const OffsetF& subwindowOffset)
4354 {
4355 auto frameOffset = GetOffsetInScreen();
4356 frameOffset -= subwindowOffset;
4357 return frameOffset;
4358 }
4359
GetPixelMap()4360 RefPtr<PixelMap> FrameNode::GetPixelMap()
4361 {
4362 auto gestureHub = GetOrCreateGestureEventHub();
4363 CHECK_NULL_RETURN(gestureHub, nullptr);
4364 RefPtr<PixelMap> pixelMap = gestureHub->GetPixelMap();
4365 // if gesture already have pixel map return directly
4366 if (pixelMap) {
4367 return pixelMap;
4368 }
4369 CHECK_NULL_RETURN(renderContext_, nullptr);
4370 pixelMap = renderContext_->GetThumbnailPixelMap();
4371 gestureHub->SetPixelMap(pixelMap);
4372 return pixelMap;
4373 }
4374
GetBaselineDistance() const4375 float FrameNode::GetBaselineDistance() const
4376 {
4377 const auto& children = frameProxy_->GetAllFrameChildren();
4378 if (children.empty()) {
4379 return geometryNode_->GetBaselineDistance();
4380 }
4381 float distance = 0.0;
4382 {
4383 auto guard = frameProxy_->GetGuard();
4384 for (const auto& child : children) {
4385 float childBaseline = child->GetBaselineDistance();
4386 distance = NearZero(distance) ? childBaseline : std::min(distance, childBaseline);
4387 }
4388 }
4389 return distance;
4390 }
4391
MarkNeedSyncRenderTree(bool needRebuild)4392 void FrameNode::MarkNeedSyncRenderTree(bool needRebuild)
4393 {
4394 if (needRebuild) {
4395 frameProxy_->ResetChildren(true);
4396 }
4397 needSyncRenderTree_ = true;
4398 }
4399
GetFrameChildByIndex(uint32_t index,bool needBuild,bool isCache,bool addToRenderTree)4400 RefPtr<UINode> FrameNode::GetFrameChildByIndex(uint32_t index, bool needBuild, bool isCache, bool addToRenderTree)
4401 {
4402 if (index != 0) {
4403 return nullptr;
4404 }
4405 return Claim(this);
4406 }
4407
GetFrameChildByIndexWithoutExpanded(uint32_t index)4408 RefPtr<UINode> FrameNode::GetFrameChildByIndexWithoutExpanded(uint32_t index)
4409 {
4410 return GetFrameChildByIndex(index, false);
4411 }
4412
GetLayoutAlgorithm(bool needReset)4413 const RefPtr<LayoutAlgorithmWrapper>& FrameNode::GetLayoutAlgorithm(bool needReset)
4414 {
4415 if ((!layoutAlgorithm_ || (needReset && layoutAlgorithm_->IsExpire())) && pattern_) {
4416 layoutAlgorithm_ = MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm());
4417 }
4418 if (needReset) {
4419 layoutAlgorithm_->SetNeedMeasure();
4420 }
4421 return layoutAlgorithm_;
4422 }
4423
SetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)4424 void FrameNode::SetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
4425 {
4426 frameProxy_->SetCacheCount(cacheCount, itemConstraint);
4427 }
4428
LayoutOverlay()4429 void FrameNode::LayoutOverlay()
4430 {
4431 auto size = geometryNode_->GetFrameSize();
4432 auto align = Alignment::TOP_LEFT;
4433 Dimension offsetX, offsetY;
4434 auto childLayoutProperty = overlayNode_->GetLayoutProperty();
4435 childLayoutProperty->GetOverlayOffset(offsetX, offsetY);
4436 auto offset = OffsetF(offsetX.ConvertToPx(), offsetY.ConvertToPx());
4437 if (childLayoutProperty->GetPositionProperty()) {
4438 align = childLayoutProperty->GetPositionProperty()->GetAlignment().value_or(align);
4439 }
4440
4441 auto childSize = overlayNode_->GetGeometryNode()->GetMarginFrameSize();
4442 auto translate = Alignment::GetAlignPosition(size, childSize, align) + offset;
4443 overlayNode_->GetGeometryNode()->SetMarginFrameOffset(translate);
4444 overlayNode_->Layout();
4445 }
4446
DoRemoveChildInRenderTree(uint32_t index,bool isAll)4447 void FrameNode::DoRemoveChildInRenderTree(uint32_t index, bool isAll)
4448 {
4449 isActive_ = false;
4450 SetActive(false);
4451 }
4452
DoSetActiveChildRange(int32_t start,int32_t end,int32_t cacheStart,int32_t cacheEnd)4453 void FrameNode::DoSetActiveChildRange(int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd)
4454 {
4455 if (start <= end) {
4456 if (start > 0 || end < 0) {
4457 SetActive(false);
4458 SetJSViewActive(false);
4459 } else {
4460 SetJSViewActive(true);
4461 }
4462 } else {
4463 if (end < 0 && start > 0) {
4464 SetActive(false);
4465 SetJSViewActive(false);
4466 } else {
4467 SetJSViewActive(true);
4468 }
4469 }
4470 }
4471
OnInspectorIdUpdate(const std::string & id)4472 void FrameNode::OnInspectorIdUpdate(const std::string& id)
4473 {
4474 renderContext_->UpdateNodeName(id);
4475 ElementRegister::GetInstance()->AddFrameNodeByInspectorId(id, AceType::WeakClaim(this));
4476 auto parent = GetAncestorNodeOfFrame();
4477 if (parent && parent->GetTag() == V2::RELATIVE_CONTAINER_ETS_TAG) {
4478 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
4479 }
4480 if (Recorder::EventRecorder::Get().IsExposureRecordEnable()) {
4481 if (exposureProcessor_) {
4482 return;
4483 }
4484 auto* context = GetContext();
4485 CHECK_NULL_VOID(context);
4486 context->AddAfterRenderTask([weak = WeakClaim(this), inspectorId = id]() {
4487 auto host = weak.Upgrade();
4488 CHECK_NULL_VOID(host);
4489 auto pageUrl = Recorder::GetPageUrlByNode(host);
4490 host->exposureProcessor_ = MakeRefPtr<Recorder::ExposureProcessor>(pageUrl, inspectorId);
4491 if (!host->exposureProcessor_->IsNeedRecord()) {
4492 return;
4493 }
4494 host->RecordExposureInner();
4495 });
4496 }
4497 }
4498
SetExposureProcessor(const RefPtr<Recorder::ExposureProcessor> & processor)4499 void FrameNode::SetExposureProcessor(const RefPtr<Recorder::ExposureProcessor>& processor)
4500 {
4501 if (exposureProcessor_ && exposureProcessor_->isListening()) {
4502 return;
4503 } else {
4504 exposureProcessor_ = MakeRefPtr<Recorder::ExposureProcessor>(processor);
4505 exposureProcessor_->SetContainerId(processor->GetContainerId());
4506 }
4507 exposureProcessor_->OnVisibleChange(true, "");
4508 RecordExposureInner();
4509 }
4510
RecordExposureInner()4511 void FrameNode::RecordExposureInner()
4512 {
4513 auto pipeline = GetContext();
4514 if (!pipeline) {
4515 auto piplineRef = PipelineContext::GetContextByContainerId(exposureProcessor_->GetContainerId());
4516 if (!piplineRef) {
4517 pipeline = piplineRef.GetRawPtr();
4518 }
4519 }
4520 CHECK_NULL_VOID(pipeline);
4521 auto callback = [weak = WeakClaim(RawPtr(exposureProcessor_)), weakNode = WeakClaim(this)](
4522 bool visible, double ratio) {
4523 auto processor = weak.Upgrade();
4524 CHECK_NULL_VOID(processor);
4525 if (!visible) {
4526 auto host = weakNode.Upgrade();
4527 auto param = host ? host->GetAutoEventParamValue("") : "";
4528 processor->OnVisibleChange(false, param);
4529 } else {
4530 processor->OnVisibleChange(visible);
4531 }
4532 };
4533 std::vector<double> ratios = { exposureProcessor_->GetRatio() };
4534 pipeline->AddVisibleAreaChangeNode(Claim(this), ratios, callback, false);
4535 exposureProcessor_->SetListenState(true);
4536 }
4537
AddFrameNodeSnapshot(bool isHit,int32_t parentId,std::vector<RectF> responseRegionList,EventTreeType type)4538 void FrameNode::AddFrameNodeSnapshot(
4539 bool isHit, int32_t parentId, std::vector<RectF> responseRegionList, EventTreeType type)
4540 {
4541 auto context = PipelineContext::GetCurrentContext();
4542 CHECK_NULL_VOID(context);
4543 auto eventMgr = context->GetEventManager();
4544 CHECK_NULL_VOID(eventMgr);
4545
4546 FrameNodeSnapshot info = { .nodeId = GetId(),
4547 .parentNodeId = parentId,
4548 .tag = GetTag(),
4549 .comId = propInspectorId_.value_or(""),
4550 .monopolizeEvents = GetMonopolizeEvents(),
4551 .isHit = isHit,
4552 .hitTestMode = static_cast<int32_t>(GetHitTestMode()),
4553 .responseRegionList = responseRegionList };
4554 eventMgr->GetEventTreeRecord(type).AddFrameNodeSnapshot(std::move(info));
4555 }
4556
GetUiExtensionId()4557 int32_t FrameNode::GetUiExtensionId()
4558 {
4559 if (pattern_) {
4560 return pattern_->GetUiExtensionId();
4561 }
4562 return -1;
4563 }
4564
WrapExtensionAbilityId(int64_t extensionOffset,int64_t abilityId)4565 int64_t FrameNode::WrapExtensionAbilityId(int64_t extensionOffset, int64_t abilityId)
4566 {
4567 if (pattern_) {
4568 return pattern_->WrapExtensionAbilityId(extensionOffset, abilityId);
4569 }
4570 return -1;
4571 }
4572
SearchExtensionElementInfoByAccessibilityIdNG(int64_t elementId,int32_t mode,int64_t offset,std::list<Accessibility::AccessibilityElementInfo> & output)4573 void FrameNode::SearchExtensionElementInfoByAccessibilityIdNG(
4574 int64_t elementId, int32_t mode, int64_t offset, std::list<Accessibility::AccessibilityElementInfo>& output)
4575 {
4576 if (pattern_) {
4577 pattern_->SearchExtensionElementInfoByAccessibilityId(elementId, mode, offset, output);
4578 }
4579 }
4580
SearchElementInfosByTextNG(int64_t elementId,const std::string & text,int64_t offset,std::list<Accessibility::AccessibilityElementInfo> & output)4581 void FrameNode::SearchElementInfosByTextNG(int64_t elementId, const std::string& text, int64_t offset,
4582 std::list<Accessibility::AccessibilityElementInfo>& output)
4583 {
4584 if (pattern_) {
4585 pattern_->SearchElementInfosByText(elementId, text, offset, output);
4586 }
4587 }
4588
FindFocusedExtensionElementInfoNG(int64_t elementId,int32_t focusType,int64_t offset,Accessibility::AccessibilityElementInfo & output)4589 void FrameNode::FindFocusedExtensionElementInfoNG(
4590 int64_t elementId, int32_t focusType, int64_t offset, Accessibility::AccessibilityElementInfo& output)
4591 {
4592 if (pattern_) {
4593 pattern_->FindFocusedElementInfo(elementId, focusType, offset, output);
4594 }
4595 }
4596
FocusMoveSearchNG(int64_t elementId,int32_t direction,int64_t offset,Accessibility::AccessibilityElementInfo & output)4597 void FrameNode::FocusMoveSearchNG(
4598 int64_t elementId, int32_t direction, int64_t offset, Accessibility::AccessibilityElementInfo& output)
4599 {
4600 if (pattern_) {
4601 pattern_->FocusMoveSearch(elementId, direction, offset, output);
4602 }
4603 }
4604
TransferExecuteAction(int64_t elementId,const std::map<std::string,std::string> & actionArguments,int32_t action,int64_t offset)4605 bool FrameNode::TransferExecuteAction(
4606 int64_t elementId, const std::map<std::string, std::string>& actionArguments, int32_t action, int64_t offset)
4607 {
4608 bool isExecuted = false;
4609 if (pattern_) {
4610 isExecuted = pattern_->TransferExecuteAction(elementId, actionArguments, action, offset);
4611 }
4612 return isExecuted;
4613 }
4614
GetOnChildTouchTestRet(const std::vector<TouchTestInfo> & touchInfo)4615 TouchResult FrameNode::GetOnChildTouchTestRet(const std::vector<TouchTestInfo>& touchInfo)
4616 {
4617 TouchResult res;
4618 res.strategy = TouchTestStrategy::DEFAULT;
4619
4620 auto func = GetOnTouchTestFunc();
4621 if (func == nullptr) {
4622 return res;
4623 }
4624 return func(touchInfo);
4625 }
4626
GetOnTouchTestFunc()4627 OnChildTouchTestFunc FrameNode::GetOnTouchTestFunc()
4628 {
4629 auto gestureHub = eventHub_->GetGestureEventHub();
4630 if (gestureHub == nullptr) {
4631 return nullptr;
4632 }
4633 auto& func = gestureHub->GetOnTouchTestFunc();
4634 return func;
4635 }
4636
CollectTouchInfos(const PointF & globalPoint,const PointF & parentRevertPoint,std::vector<TouchTestInfo> & touchInfos)4637 void FrameNode::CollectTouchInfos(
4638 const PointF& globalPoint, const PointF& parentRevertPoint, std::vector<TouchTestInfo>& touchInfos)
4639 {
4640 if (GetOnTouchTestFunc() == nullptr) {
4641 return;
4642 }
4643
4644 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
4645 const auto& child = iter->Upgrade();
4646 if (!child) {
4647 continue;
4648 }
4649
4650 TouchTestInfo info;
4651 if (!child->GetInspectorId().has_value()) {
4652 continue;
4653 }
4654 info.id = child->GetInspectorId().value();
4655 info.windowPoint = globalPoint;
4656 info.currentCmpPoint = parentRevertPoint;
4657
4658 auto renderContext = child->GetRenderContext();
4659 CHECK_NULL_VOID(renderContext);
4660 auto origRect = renderContext->GetPaintRectWithoutTransform();
4661 auto revertPoint = parentRevertPoint;
4662 renderContext->GetPointWithRevert(revertPoint);
4663 auto subRevertPoint = revertPoint - origRect.GetOffset();
4664 info.subCmpPoint = subRevertPoint;
4665
4666 info.subRect = child->GetGeometryNode()->GetFrameRect();
4667
4668 touchInfos.emplace_back(info);
4669 }
4670 }
4671
GetDispatchFrameNode(const TouchResult & touchRes)4672 RefPtr<FrameNode> FrameNode::GetDispatchFrameNode(const TouchResult& touchRes)
4673 {
4674 if (touchRes.strategy != TouchTestStrategy::FORWARD_COMPETITION &&
4675 touchRes.strategy != TouchTestStrategy::FORWARD) {
4676 return nullptr;
4677 }
4678
4679 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
4680 const auto& child = iter->Upgrade();
4681 if (!child) {
4682 continue;
4683 }
4684 std::string id = child->GetInspectorId().value_or("");
4685 if ((!touchRes.id.empty()) && (touchRes.id == id)) {
4686 return child;
4687 }
4688 }
4689 return nullptr;
4690 }
4691
CalculateCachedTransformRelativeOffset(uint64_t nanoTimestamp)4692 OffsetF FrameNode::CalculateCachedTransformRelativeOffset(uint64_t nanoTimestamp)
4693 {
4694 auto context = GetRenderContext();
4695 CHECK_NULL_RETURN(context, OffsetF());
4696 auto offset = context->GetPaintRectWithTransform().GetOffset();
4697
4698 auto parent = GetAncestorNodeOfFrame(true);
4699 if (parent) {
4700 auto parentTimestampOffset = parent->GetCachedTransformRelativeOffset();
4701 if (parentTimestampOffset.first == nanoTimestamp) {
4702 auto result = offset + parentTimestampOffset.second;
4703 SetCachedTransformRelativeOffset({ nanoTimestamp, result });
4704 return result;
4705 }
4706 auto result = offset + parent->CalculateCachedTransformRelativeOffset(nanoTimestamp);
4707 SetCachedTransformRelativeOffset({ nanoTimestamp, result });
4708 return result;
4709 }
4710 SetCachedTransformRelativeOffset({ nanoTimestamp, offset });
4711 return offset;
4712 }
4713
CalculateOffsetRelativeToWindow(uint64_t nanoTimestamp)4714 OffsetF FrameNode::CalculateOffsetRelativeToWindow(uint64_t nanoTimestamp)
4715 {
4716 auto currOffset = geometryNode_->GetFrameOffset();
4717 if (renderContext_ && renderContext_->GetPositionProperty()) {
4718 if (renderContext_->GetPositionProperty()->HasPosition()) {
4719 auto renderPosition =
4720 ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
4721 currOffset.SetX(static_cast<float>(renderPosition.first));
4722 currOffset.SetY(static_cast<float>(renderPosition.second));
4723 }
4724 }
4725
4726 auto parent = GetAncestorNodeOfFrame(true);
4727 if (parent) {
4728 auto parentTimestampOffset = parent->GetCachedGlobalOffset();
4729 if (parentTimestampOffset.first == nanoTimestamp) {
4730 auto result = currOffset + parentTimestampOffset.second;
4731 SetCachedGlobalOffset({ nanoTimestamp, result });
4732 return result;
4733 } else {
4734 auto result = currOffset + parent->CalculateOffsetRelativeToWindow(nanoTimestamp);
4735 SetCachedGlobalOffset({ nanoTimestamp, result });
4736 return result;
4737 }
4738 } else {
4739 SetCachedGlobalOffset({ nanoTimestamp, currOffset });
4740 return currOffset;
4741 }
4742 }
4743
GetNodeContainer()4744 RefPtr<FrameNode> FrameNode::GetNodeContainer()
4745 {
4746 if (GetTag() == V2::NODE_CONTAINER_ETS_TAG) {
4747 return Claim(this);
4748 }
4749 auto parent = GetParent();
4750 while (parent && parent->GetTag() != V2::NODE_CONTAINER_ETS_TAG) {
4751 parent = parent->GetParent();
4752 }
4753 return AceType::DynamicCast<FrameNode>(parent);
4754 }
4755
InitLastArea()4756 void FrameNode::InitLastArea()
4757 {
4758 if (!lastFrameRect_) {
4759 lastFrameRect_ = std::make_unique<RectF>();
4760 }
4761 if (!lastParentOffsetToWindow_) {
4762 lastParentOffsetToWindow_ = std::make_unique<OffsetF>();
4763 }
4764 }
4765
SetParentLayoutConstraint(const SizeF & size) const4766 bool FrameNode::SetParentLayoutConstraint(const SizeF& size) const
4767 {
4768 LayoutConstraintF layoutConstraint;
4769 layoutConstraint.UpdatePercentReference(size);
4770 layoutConstraint.UpdateMaxSizeWithCheck(size);
4771 layoutConstraint.UpdateIllegalParentIdealSizeWithCheck(OptionalSize(size));
4772 layoutProperty_->UpdateParentLayoutConstraint(layoutConstraint);
4773 return true;
4774 }
4775
ForceSyncGeometryNode()4776 void FrameNode::ForceSyncGeometryNode()
4777 {
4778 CHECK_NULL_VOID(renderContext_);
4779 oldGeometryNode_.Reset();
4780 renderContext_->SavePaintRect();
4781 renderContext_->SyncGeometryProperties(RawPtr(geometryNode_));
4782 }
4783
GetCachedGlobalOffset() const4784 const std::pair<uint64_t, OffsetF>& FrameNode::GetCachedGlobalOffset() const
4785 {
4786 return cachedGlobalOffset_;
4787 }
4788
SetCachedGlobalOffset(const std::pair<uint64_t,OffsetF> & timestampOffset)4789 void FrameNode::SetCachedGlobalOffset(const std::pair<uint64_t, OffsetF>& timestampOffset)
4790 {
4791 cachedGlobalOffset_ = timestampOffset;
4792 }
GetCachedTransformRelativeOffset() const4793 const std::pair<uint64_t, OffsetF>& FrameNode::GetCachedTransformRelativeOffset() const
4794 {
4795 return cachedTransformRelativeOffset_;
4796 }
4797
SetCachedTransformRelativeOffset(const std::pair<uint64_t,OffsetF> & timestampOffset)4798 void FrameNode::SetCachedTransformRelativeOffset(const std::pair<uint64_t, OffsetF>& timestampOffset)
4799 {
4800 cachedTransformRelativeOffset_ = timestampOffset;
4801 }
4802
PaintDebugBoundary(bool flag)4803 void FrameNode::PaintDebugBoundary(bool flag)
4804 {
4805 if (!isActive_) {
4806 return;
4807 }
4808 if (renderContext_) {
4809 renderContext_->PaintDebugBoundary(flag);
4810 }
4811 }
4812
TriggerOnTouchIntercept(const TouchEvent & touchEvent)4813 HitTestMode FrameNode::TriggerOnTouchIntercept(const TouchEvent& touchEvent)
4814 {
4815 auto gestureHub = eventHub_->GetGestureEventHub();
4816 CHECK_NULL_RETURN(gestureHub, HitTestMode::HTMDEFAULT);
4817 auto onTouchIntercept = gestureHub->GetOnTouchIntercept();
4818 CHECK_NULL_RETURN(onTouchIntercept, HitTestMode::HTMDEFAULT);
4819 TouchEventInfo event("touchEvent");
4820 event.SetTimeStamp(touchEvent.time);
4821 event.SetDeviceId(touchEvent.deviceId);
4822 event.SetPointerEvent(touchEvent.pointerEvent);
4823 TouchLocationInfo changedInfo("onTouch", touchEvent.originalId);
4824 PointF lastLocalPoint(touchEvent.x, touchEvent.y);
4825 NGGestureRecognizer::Transform(lastLocalPoint, Claim(this), false, false);
4826 auto localX = static_cast<float>(lastLocalPoint.GetX());
4827 auto localY = static_cast<float>(lastLocalPoint.GetY());
4828 changedInfo.SetLocalLocation(Offset(localX, localY));
4829 changedInfo.SetGlobalLocation(Offset(touchEvent.x, touchEvent.y));
4830 changedInfo.SetScreenLocation(Offset(touchEvent.screenX, touchEvent.screenY));
4831 changedInfo.SetTouchType(touchEvent.type);
4832 changedInfo.SetForce(touchEvent.force);
4833 if (touchEvent.tiltX.has_value()) {
4834 changedInfo.SetTiltX(touchEvent.tiltX.value());
4835 }
4836 if (touchEvent.tiltY.has_value()) {
4837 changedInfo.SetTiltY(touchEvent.tiltY.value());
4838 }
4839 changedInfo.SetSourceTool(touchEvent.sourceTool);
4840 event.AddChangedTouchLocationInfo(std::move(changedInfo));
4841
4842 AddTouchEventAllFingersInfo(event, touchEvent);
4843 event.SetSourceDevice(touchEvent.sourceType);
4844 event.SetForce(touchEvent.force);
4845 if (touchEvent.tiltX.has_value()) {
4846 event.SetTiltX(touchEvent.tiltX.value());
4847 }
4848 if (touchEvent.tiltY.has_value()) {
4849 event.SetTiltY(touchEvent.tiltY.value());
4850 }
4851 event.SetSourceTool(touchEvent.sourceTool);
4852 auto result = onTouchIntercept(event);
4853 SetHitTestMode(result);
4854 return result;
4855 }
4856
AddTouchEventAllFingersInfo(TouchEventInfo & event,const TouchEvent & touchEvent)4857 void FrameNode::AddTouchEventAllFingersInfo(TouchEventInfo& event, const TouchEvent& touchEvent)
4858 {
4859 // all fingers collection
4860 for (const auto& item : touchEvent.pointers) {
4861 float globalX = item.x;
4862 float globalY = item.y;
4863 float screenX = item.screenX;
4864 float screenY = item.screenY;
4865 PointF localPoint(globalX, globalY);
4866 NGGestureRecognizer::Transform(localPoint, Claim(this), false, false);
4867 auto localX = static_cast<float>(localPoint.GetX());
4868 auto localY = static_cast<float>(localPoint.GetY());
4869 TouchLocationInfo info("onTouch", item.originalId);
4870 info.SetGlobalLocation(Offset(globalX, globalY));
4871 info.SetLocalLocation(Offset(localX, localY));
4872 info.SetScreenLocation(Offset(screenX, screenY));
4873 info.SetTouchType(touchEvent.type);
4874 info.SetForce(item.force);
4875 if (item.tiltX.has_value()) {
4876 info.SetTiltX(item.tiltX.value());
4877 }
4878 if (item.tiltY.has_value()) {
4879 info.SetTiltY(item.tiltY.value());
4880 }
4881 info.SetSourceTool(item.sourceTool);
4882 event.AddTouchLocationInfo(std::move(info));
4883 }
4884 }
4885
AttachContext(PipelineContext * context,bool recursive)4886 void FrameNode::AttachContext(PipelineContext* context, bool recursive)
4887 {
4888 UINode::AttachContext(context, recursive);
4889 eventHub_->OnAttachContext(context);
4890 pattern_->OnAttachContext(context);
4891 }
4892
DetachContext(bool recursive)4893 void FrameNode::DetachContext(bool recursive)
4894 {
4895 CHECK_NULL_VOID(context_);
4896 pattern_->OnDetachContext(context_);
4897 eventHub_->OnDetachContext(context_);
4898 UINode::DetachContext(recursive);
4899 }
4900
ApplyFrameNodeTranformToRect(const RectF & rect,const RefPtr<FrameNode> & parent) const4901 RectF FrameNode::ApplyFrameNodeTranformToRect(const RectF& rect, const RefPtr<FrameNode>& parent) const
4902 {
4903 RectF newRect = rect;
4904 if (!parent) {
4905 return newRect;
4906 }
4907
4908 auto parentRenderContext = parent->GetRenderContext();
4909 if (!parentRenderContext) {
4910 return newRect;
4911 }
4912
4913 auto parentScale = parentRenderContext->GetTransformScale();
4914 auto offset = rect.GetOffset();
4915 if (parentScale) {
4916 newRect.SetWidth(rect.Width() * parentScale.value().x);
4917 newRect.SetHeight(rect.Height() * parentScale.value().y);
4918 offset = OffsetF(offset.GetX() * parentScale.value().x, offset.GetY() * parentScale.value().y);
4919 }
4920 offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
4921 newRect.SetOffset(offset);
4922 return newRect;
4923 }
4924
GetVisibleRect(RectF & visibleRect,RectF & frameRect) const4925 void FrameNode::GetVisibleRect(RectF& visibleRect, RectF& frameRect) const
4926 {
4927 visibleRect = GetPaintRectWithTransform();
4928 frameRect = visibleRect;
4929 RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame(true);
4930 if (!parentUi) {
4931 visibleRect.SetWidth(0.0f);
4932 visibleRect.SetHeight(0.0f);
4933 return;
4934 }
4935 while (parentUi) {
4936 visibleRect = ApplyFrameNodeTranformToRect(visibleRect, parentUi);
4937 auto parentRect = parentUi->GetPaintRectWithTransform();
4938 visibleRect = visibleRect.Constrain(parentRect);
4939 if (visibleRect.IsEmpty()) {
4940 return;
4941 }
4942 frameRect = ApplyFrameNodeTranformToRect(frameRect, parentUi);
4943 parentUi = parentUi->GetAncestorNodeOfFrame(true);
4944 }
4945 }
4946
AllowVisibleAreaCheck() const4947 bool FrameNode::AllowVisibleAreaCheck() const
4948 {
4949 return IsOnMainTree() || (pattern_ && pattern_->AllowVisibleAreaCheck());
4950 }
4951
GetVisibleRectWithClip(RectF & visibleRect,RectF & visibleInnerRect,RectF & frameRect)4952 void FrameNode::GetVisibleRectWithClip(RectF& visibleRect, RectF& visibleInnerRect, RectF& frameRect)
4953 {
4954 visibleRect = GetPaintRectWithTransform();
4955 frameRect = visibleRect;
4956 visibleInnerRect = visibleRect;
4957 RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame(true);
4958 if (!AllowVisibleAreaCheck() || !parentUi || IsFrameDisappear()) {
4959 visibleRect.SetWidth(0.0f);
4960 visibleRect.SetHeight(0.0f);
4961 visibleInnerRect.SetWidth(0.0f);
4962 visibleInnerRect.SetHeight(0.0f);
4963 return;
4964 }
4965
4966 while (parentUi) {
4967 visibleRect = ApplyFrameNodeTranformToRect(visibleRect, parentUi);
4968 auto parentRect = parentUi->GetPaintRectWithTransform();
4969 if (!visibleRect.IsEmpty()) {
4970 visibleRect = visibleRect.Constrain(parentRect);
4971 }
4972
4973 if (isCalculateInnerVisibleRectClip_) {
4974 visibleInnerRect = ApplyFrameNodeTranformToRect(visibleInnerRect, parentUi);
4975 auto parentContext = parentUi->GetRenderContext();
4976 if (!visibleInnerRect.IsEmpty() && ((parentContext && parentContext->GetClipEdge().value_or(false)) ||
4977 parentUi->IsWindowBoundary() || parentUi->GetTag() == V2::ROOT_ETS_TAG)) {
4978 visibleInnerRect = visibleInnerRect.Constrain(parentRect);
4979 }
4980 }
4981
4982 if (visibleRect.IsEmpty() && (!isCalculateInnerVisibleRectClip_ || visibleInnerRect.IsEmpty())) {
4983 visibleInnerRect = visibleRect;
4984 return;
4985 }
4986 frameRect = ApplyFrameNodeTranformToRect(frameRect, parentUi);
4987 parentUi = parentUi->GetAncestorNodeOfFrame(true);
4988 }
4989
4990 if (!isCalculateInnerVisibleRectClip_) {
4991 visibleInnerRect = visibleRect;
4992 }
4993 }
4994
GetCacheVisibleRect(uint64_t timestamp)4995 CacheVisibleRectResult FrameNode::GetCacheVisibleRect(uint64_t timestamp)
4996 {
4997 RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame(true);
4998 auto rectToParent = GetPaintRectWithTransform();
4999 auto scale = GetTransformScale();
5000
5001 if (!parentUi || IsWindowBoundary()) {
5002 cachedVisibleRectResult_ = {timestamp,
5003 {rectToParent.GetOffset(), rectToParent, rectToParent, scale, rectToParent, rectToParent}};
5004 return cachedVisibleRectResult_.second;
5005 }
5006
5007 if (parentUi->cachedVisibleRectResult_.first == timestamp) {
5008 auto parentCacheVisibleRectResult = parentUi->cachedVisibleRectResult_.second;
5009 return CalculateCacheVisibleRect(parentCacheVisibleRectResult, parentUi, rectToParent, scale, timestamp);
5010 }
5011
5012 CacheVisibleRectResult parentCacheVisibleRectResult = parentUi->GetCacheVisibleRect(timestamp);
5013 return CalculateCacheVisibleRect(parentCacheVisibleRectResult, parentUi, rectToParent, scale, timestamp);
5014 }
5015
CalculateCacheVisibleRect(CacheVisibleRectResult & parentCacheVisibleRect,const RefPtr<FrameNode> & parentUi,RectF & rectToParent,VectorF scale,uint64_t timestamp)5016 CacheVisibleRectResult FrameNode::CalculateCacheVisibleRect(CacheVisibleRectResult& parentCacheVisibleRect,
5017 const RefPtr<FrameNode>& parentUi, RectF& rectToParent, VectorF scale, uint64_t timestamp)
5018 {
5019 auto parentRenderContext = parentUi->GetRenderContext();
5020 OffsetF windowOffset;
5021 auto offset = rectToParent.GetOffset();
5022 if (parentRenderContext && parentRenderContext->GetTransformScale()) {
5023 auto parentScale = parentRenderContext->GetTransformScale();
5024 offset = OffsetF(offset.GetX() * parentScale.value().x, offset.GetY() * parentScale.value().y);
5025 }
5026 windowOffset = parentCacheVisibleRect.windowOffset + offset;
5027
5028 RectF rect;
5029 rect.SetOffset(windowOffset);
5030 rect.SetWidth(rectToParent.Width() * parentCacheVisibleRect.cumulativeScale.x);
5031 rect.SetHeight(rectToParent.Height() * parentCacheVisibleRect.cumulativeScale.y);
5032
5033 auto visibleRect = rect.Constrain(parentCacheVisibleRect.visibleRect);
5034 auto innerVisibleRect = rect;
5035 auto innerBoundaryRect = parentCacheVisibleRect.innerBoundaryRect;
5036 if (parentRenderContext && parentRenderContext->GetClipEdge().value_or(false)) {
5037 innerBoundaryRect = parentCacheVisibleRect.innerVisibleRect.Constrain(innerBoundaryRect);
5038 }
5039 innerVisibleRect = rect.Constrain(innerBoundaryRect);
5040
5041 scale = {scale.x * parentCacheVisibleRect.cumulativeScale.x, scale.y * parentCacheVisibleRect.cumulativeScale.y};
5042 cachedVisibleRectResult_ = { timestamp,
5043 { windowOffset, visibleRect, innerVisibleRect, scale, rect, innerBoundaryRect } };
5044 return {windowOffset, visibleRect, innerVisibleRect, scale, rect, innerBoundaryRect};
5045 }
5046
ChangeSensitiveStyle(bool isSensitive)5047 void FrameNode::ChangeSensitiveStyle(bool isSensitive)
5048 {
5049 pattern_->OnSensitiveStyleChange(isSensitive);
5050 }
5051
IsContextTransparent()5052 bool FrameNode::IsContextTransparent()
5053 {
5054 ACE_SCOPED_TRACE("Transparent detection");
5055 const auto& rect = renderContext_->GetPaintRectWithTransform();
5056 auto width = rect.Width();
5057 auto height = rect.Height();
5058 if (renderContext_->GetOpacity().has_value() && renderContext_->GetOpacity().value() <= MIN_OPACITY) {
5059 return true;
5060 }
5061 if (layoutTags_.find(GetTag()) == layoutTags_.end()) {
5062 if (width > MIN_WIDTH && height > MIN_HEIGHT &&
5063 static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)) == 0) {
5064 return false;
5065 }
5066 } else {
5067 if (width > MIN_WIDTH && height > MIN_HEIGHT &&
5068 static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)) == 0 &&
5069 renderContext_->GetBackgroundColor()->ColorToString().compare("#00000000") != 0) {
5070 return false;
5071 }
5072 }
5073 for (const auto& item : GetChildren()) {
5074 if (!item->IsContextTransparent()) {
5075 return false;
5076 }
5077 }
5078 return true;
5079 }
5080
GetOrRefreshRevertMatrixFromCache(bool forceRefresh)5081 Matrix4& FrameNode::GetOrRefreshRevertMatrixFromCache(bool forceRefresh)
5082 {
5083 auto pipeline = NG::PipelineContext::GetCurrentContext();
5084 CHECK_NULL_RETURN(pipeline, localRevertMatrix_);
5085 auto nanoTimestamp = pipeline->GetVsyncTime();
5086 auto rect = renderContext_->GetPaintRectWithoutTransform();
5087 // the caller is trying to refresh cache forcedly or the cache is invalid
5088 if (!isLocalRevertMatrixAvailable_ || forceRefresh || prePaintRect_ != rect ||
5089 getCacheNanoTime_ + MATRIX_CACHE_TIME_THRESHOLD < nanoTimestamp) {
5090 localRevertMatrix_ = renderContext_->GetRevertMatrix();
5091 isLocalRevertMatrixAvailable_ = true;
5092 getCacheNanoTime_ = nanoTimestamp;
5093 prePaintRect_ = rect;
5094 return localRevertMatrix_;
5095 }
5096
5097 // cache valid
5098 return localRevertMatrix_;
5099 }
5100
5101 // apply the matrix to the given point specified by dst
MapPointTo(PointF & dst,Matrix4 & matrix)5102 void FrameNode::MapPointTo(PointF& dst, Matrix4& matrix)
5103 {
5104 Point tmp(dst.GetX(), dst.GetY());
5105 auto transformPoint = matrix * tmp;
5106 dst.SetX(transformPoint.GetX());
5107 dst.SetY(transformPoint.GetY());
5108 }
5109
SetSuggestOpIncMarked(bool flag)5110 void FrameNode::SetSuggestOpIncMarked(bool flag)
5111 {
5112 if (flag) {
5113 suggestOpIncByte_ |= SUGGEST_OPINC_MARKED_MASK;
5114 } else {
5115 suggestOpIncByte_ &= (~SUGGEST_OPINC_MARKED_MASK);
5116 }
5117 }
5118
GetSuggestOpIncMarked()5119 bool FrameNode::GetSuggestOpIncMarked()
5120 {
5121 return (suggestOpIncByte_ & SUGGEST_OPINC_MARKED_MASK) > 0;
5122 }
5123
SetCanSuggestOpInc(bool flag)5124 void FrameNode::SetCanSuggestOpInc(bool flag)
5125 {
5126 if (flag) {
5127 suggestOpIncByte_ |= CAN_SUGGEST_OPINC_MASK;
5128 } else {
5129 suggestOpIncByte_ &= (~CAN_SUGGEST_OPINC_MASK);
5130 }
5131 }
5132
GetCanSuggestOpInc()5133 bool FrameNode::GetCanSuggestOpInc()
5134 {
5135 return (suggestOpIncByte_ & CAN_SUGGEST_OPINC_MASK) > 0;
5136 }
5137
SetApplicationRenderGroupMarked(bool flag)5138 void FrameNode::SetApplicationRenderGroupMarked(bool flag)
5139 {
5140 if (flag) {
5141 suggestOpIncByte_ |= APP_RENDER_GROUP_MARKED_MASK;
5142 } else {
5143 suggestOpIncByte_ &= (~APP_RENDER_GROUP_MARKED_MASK);
5144 }
5145 }
5146
GetApplicationRenderGroupMarked()5147 bool FrameNode::GetApplicationRenderGroupMarked()
5148 {
5149 return (suggestOpIncByte_ & APP_RENDER_GROUP_MARKED_MASK) > 0;
5150 }
5151
SetSuggestOpIncActivatedOnce()5152 void FrameNode::SetSuggestOpIncActivatedOnce()
5153 {
5154 suggestOpIncByte_ |= SUGGEST_OPINC_ACTIVATED_ONCE;
5155 }
5156
GetSuggestOpIncActivatedOnce()5157 bool FrameNode::GetSuggestOpIncActivatedOnce()
5158 {
5159 return (suggestOpIncByte_ & SUGGEST_OPINC_ACTIVATED_ONCE) > 0;
5160 }
5161
SetOpIncGroupCheckedThrough(bool flag)5162 void FrameNode::SetOpIncGroupCheckedThrough(bool flag)
5163 {
5164 if (flag) {
5165 suggestOpIncByte_ |= SUGGEST_OPINC_CHECKED_THROUGH;
5166 } else {
5167 suggestOpIncByte_ &= (~SUGGEST_OPINC_CHECKED_THROUGH);
5168 }
5169 }
5170
GetOpIncGroupCheckedThrough()5171 bool FrameNode::GetOpIncGroupCheckedThrough()
5172 {
5173 return (suggestOpIncByte_ & SUGGEST_OPINC_CHECKED_THROUGH) > 0;
5174 }
5175
SetOpIncCheckedOnce()5176 void FrameNode::SetOpIncCheckedOnce()
5177 {
5178 suggestOpIncByte_ |= SUGGEST_OPINC_CHCKED_ONCE;
5179 }
GetOpIncCheckedOnce()5180 bool FrameNode::GetOpIncCheckedOnce()
5181 {
5182 return (suggestOpIncByte_ & SUGGEST_OPINC_CHCKED_ONCE) > 0;
5183 }
5184
MarkSuggestOpIncGroup(bool suggest,bool calc)5185 bool FrameNode::MarkSuggestOpIncGroup(bool suggest, bool calc)
5186 {
5187 CHECK_NULL_RETURN(renderContext_, false);
5188 if (!GetSuggestOpIncMarked() && GetCanSuggestOpInc()) {
5189 renderContext_->SuggestOpIncNode(suggest, calc);
5190 SetSuggestOpIncMarked(true);
5191 }
5192 return true;
5193 }
5194
IsOpIncValidNode(const SizeF & boundary,int32_t childNumber)5195 OPINC_TYPE_E FrameNode::IsOpIncValidNode(const SizeF& boundary, int32_t childNumber)
5196 {
5197 auto ret = GetPattern()->OpIncType();
5198 switch (ret) {
5199 case OPINC_NODE:
5200 SetCanSuggestOpInc(true);
5201 break;
5202 case OPINC_PARENT_POSSIBLE:
5203 break;
5204 case OPINC_NODE_POSSIBLE: {
5205 int32_t height = static_cast<int>(GetGeometryNode()->GetFrameSize().Height());
5206 int32_t width = static_cast<int>(GetGeometryNode()->GetFrameSize().Width());
5207 int32_t heightBoundary = static_cast<int>(boundary.Height() * HIGHT_RATIO_LIMIT);
5208 int32_t area = height * width;
5209 if (area >= MIN_OPINC_AREA && height <= heightBoundary) {
5210 SetCanSuggestOpInc(true);
5211 ret = OPINC_NODE;
5212 } else if (height > heightBoundary) {
5213 ret = OPINC_PARENT_POSSIBLE;
5214 } else {
5215 ret = OPINC_SUGGESTED_OR_EXCLUDED;
5216 }
5217 break;
5218 }
5219 default:
5220 break;
5221 }
5222 return ret;
5223 }
5224
GetAllChildren()5225 ChildrenListWithGuard FrameNode::GetAllChildren()
5226 {
5227 // frameProxy_ never be null in frame node;
5228 return frameProxy_->GetCurrentFrameChildren();
5229 }
5230
FindSuggestOpIncNode(std::string & path,const SizeF & boundary,int32_t depth)5231 OPINC_TYPE_E FrameNode::FindSuggestOpIncNode(std::string& path, const SizeF& boundary, int32_t depth)
5232 {
5233 if (GetSuggestOpIncActivatedOnce()) {
5234 return OPINC_SUGGESTED_OR_EXCLUDED;
5235 }
5236 SetSuggestOpIncActivatedOnce();
5237
5238 if (GetApplicationRenderGroupMarked()) {
5239 return OPINC_INVALID;
5240 }
5241 auto status = IsOpIncValidNode(boundary);
5242 if (SystemProperties::GetDebugEnabled()) {
5243 const auto& hostTag = GetHostTag();
5244 path = path + " --> " + hostTag;
5245 LOGD("FindSuggestOpIncNode : %{public}s, with depth %{public}d, boundary: %{public}f, self: %{public}f, "
5246 "status: %{public}d",
5247 path.c_str(), depth, boundary.Height(), GetGeometryNode()->GetFrameSize().Height(), status);
5248 }
5249 if (status == OPINC_NODE) {
5250 MarkSuggestOpIncGroup(true, true);
5251 return OPINC_SUGGESTED_OR_EXCLUDED;
5252 } else if (status == OPINC_SUGGESTED_OR_EXCLUDED) {
5253 return OPINC_SUGGESTED_OR_EXCLUDED;
5254 } else if (status == OPINC_PARENT_POSSIBLE) {
5255 for (auto child : GetAllChildren()) {
5256 if (!child) {
5257 continue;
5258 }
5259 auto frameNode = AceType::DynamicCast<FrameNode>(child);
5260 if (frameNode) {
5261 frameNode->FindSuggestOpIncNode(path, boundary, depth + 1);
5262 }
5263 }
5264 return OPINC_PARENT_POSSIBLE;
5265 } else if (status == OPINC_INVALID) {
5266 return OPINC_INVALID;
5267 }
5268 return OPINC_SUGGESTED_OR_EXCLUDED;
5269 }
5270
MarkAndCheckNewOpIncNode()5271 void FrameNode::MarkAndCheckNewOpIncNode()
5272 {
5273 auto parent = GetAncestorNodeOfFrame();
5274 CHECK_NULL_VOID(parent);
5275 if (parent->GetSuggestOpIncActivatedOnce() && !GetSuggestOpIncActivatedOnce()) {
5276 SetSuggestOpIncActivatedOnce();
5277 if (!parent->GetOpIncCheckedOnce()) {
5278 parent->SetOpIncCheckedOnce();
5279 auto status = IsOpIncValidNode(parent->GetGeometryNode()->GetFrameSize());
5280 if (status == OPINC_NODE) {
5281 parent->SetOpIncGroupCheckedThrough(true);
5282 } else if (FrameNode::GetValidLeafChildNumber(Claim(this), THRESH_CHILD_NO) >= THRESH_CHILD_NO) {
5283 parent->SetOpIncGroupCheckedThrough(true);
5284 } else {
5285 parent->SetOpIncGroupCheckedThrough(false);
5286 }
5287 }
5288 if (parent->GetOpIncGroupCheckedThrough()) {
5289 SetCanSuggestOpInc(true);
5290 MarkSuggestOpIncGroup(true, true);
5291 }
5292 }
5293 }
5294
GetValidLeafChildNumber(const RefPtr<FrameNode> & host,int32_t thresh)5295 int FrameNode::GetValidLeafChildNumber(const RefPtr<FrameNode>& host, int32_t thresh)
5296 {
5297 CHECK_NULL_RETURN(host, 0);
5298 auto total = 0;
5299 auto childSize = host->GetTotalChildCount();
5300 if (childSize < 1) {
5301 return 1;
5302 }
5303 for (auto i = 0; i < childSize; i++) {
5304 auto child = AceType::DynamicCast<FrameNode>(host->GetChildByIndex(i));
5305 if (!child) {
5306 continue;
5307 }
5308 total += GetValidLeafChildNumber(child, thresh);
5309 if (total >= thresh) {
5310 return total;
5311 }
5312 }
5313 return total;
5314 }
5315
TriggerShouldParallelInnerWith(const ResponseLinkResult & currentRecognizers,const ResponseLinkResult & responseLinkRecognizers)5316 void FrameNode::TriggerShouldParallelInnerWith(
5317 const ResponseLinkResult& currentRecognizers, const ResponseLinkResult& responseLinkRecognizers)
5318 {
5319 auto gestureHub = eventHub_->GetGestureEventHub();
5320 CHECK_NULL_VOID(gestureHub);
5321 auto shouldBuiltInRecognizerParallelWithFunc = gestureHub->GetParallelInnerGestureToFunc();
5322 CHECK_NULL_VOID(shouldBuiltInRecognizerParallelWithFunc);
5323 std::map<GestureTypeName, std::vector<RefPtr<NGGestureRecognizer>>> sortedResponseLinkRecognizers;
5324
5325 for (const auto& item : responseLinkRecognizers) {
5326 auto recognizer = AceType::DynamicCast<NGGestureRecognizer>(item);
5327 if (!recognizer) {
5328 continue;
5329 }
5330 auto type = recognizer->GetRecognizerType();
5331 sortedResponseLinkRecognizers[type].emplace_back(item);
5332 }
5333
5334 for (const auto& item : currentRecognizers) {
5335 if (!item->IsSystemGesture() || item->GetRecognizerType() != GestureTypeName::PAN_GESTURE) {
5336 continue;
5337 }
5338 auto multiRecognizer = AceType::DynamicCast<MultiFingersRecognizer>(item);
5339 if (!multiRecognizer || multiRecognizer->GetTouchPointsSize() > 1) {
5340 continue;
5341 }
5342 auto iter = sortedResponseLinkRecognizers.find(item->GetRecognizerType());
5343 if (iter == sortedResponseLinkRecognizers.end() || iter->second.empty()) {
5344 continue;
5345 }
5346 auto result = shouldBuiltInRecognizerParallelWithFunc(item, iter->second);
5347 if (result && item != result) {
5348 item->SetBridgeMode(true);
5349 result->AddBridgeObj(item);
5350 }
5351 }
5352 }
5353
ClearSubtreeLayoutAlgorithm(bool includeSelf,bool clearEntireTree)5354 void FrameNode::ClearSubtreeLayoutAlgorithm(bool includeSelf, bool clearEntireTree)
5355 {
5356 // return when reaches a child that has no layoutAlgorithm and no need to clear the entire tree
5357 if (!layoutAlgorithm_ && !clearEntireTree) {
5358 return;
5359 }
5360 // include Self might be false for the first ClearSubtreeLayoutAlgorithm enter,
5361 // but children should always include themselves
5362 if (includeSelf) {
5363 layoutAlgorithm_ = nullptr;
5364 }
5365 for (const auto& child : GetChildren()) {
5366 child->ClearSubtreeLayoutAlgorithm(true, clearEntireTree);
5367 }
5368 }
5369
OnSyncGeometryFrameFinish(const RectF & paintRect)5370 void FrameNode::OnSyncGeometryFrameFinish(const RectF& paintRect)
5371 {
5372 if (syncedFramePaintRect_.has_value() && syncedFramePaintRect_.value() != paintRect) {
5373 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_GEOMETRY_CHANGE);
5374 if (AnimationUtils::IsImplicitAnimationOpen()) {
5375 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_START_ANIMATION);
5376 }
5377 }
5378 syncedFramePaintRect_ = paintRect;
5379 }
5380
AddFrameNodeChangeInfoFlag(FrameNodeChangeInfoFlag changeFlag)5381 void FrameNode::AddFrameNodeChangeInfoFlag(FrameNodeChangeInfoFlag changeFlag)
5382 {
5383 if (changeInfoFlag_ == FRAME_NODE_CHANGE_INFO_NONE) {
5384 auto context = GetContext();
5385 CHECK_NULL_VOID(context);
5386 if (!context->AddChangedFrameNode(WeakClaim(this))) {
5387 return;
5388 }
5389 }
5390 changeInfoFlag_ = changeInfoFlag_ | changeFlag;
5391 }
5392
RegisterNodeChangeListener()5393 void FrameNode::RegisterNodeChangeListener()
5394 {
5395 auto context = GetContext();
5396 CHECK_NULL_VOID(context);
5397 context->AddFrameNodeChangeListener(WeakClaim(this));
5398 }
5399
UnregisterNodeChangeListener()5400 void FrameNode::UnregisterNodeChangeListener()
5401 {
5402 auto context = GetContext();
5403 CHECK_NULL_VOID(context);
5404 context->RemoveFrameNodeChangeListener(GetId());
5405 }
5406
ProcessFrameNodeChangeFlag()5407 void FrameNode::ProcessFrameNodeChangeFlag()
5408 {
5409 auto changeFlag = FRAME_NODE_CHANGE_INFO_NONE;
5410 auto parent = Claim(this);
5411 while (parent) {
5412 if (parent->GetChangeInfoFlag() != FRAME_NODE_CHANGE_INFO_NONE) {
5413 changeFlag = changeFlag | parent->GetChangeInfoFlag();
5414 }
5415 parent = parent->GetAncestorNodeOfFrame(true);
5416 }
5417 if (changeFlag == FRAME_NODE_CHANGE_INFO_NONE) {
5418 return;
5419 }
5420 auto pattern = GetPattern();
5421 if (pattern) {
5422 pattern->OnFrameNodeChanged(changeFlag);
5423 }
5424 }
5425
OnNodeTransformInfoUpdate(bool changed)5426 void FrameNode::OnNodeTransformInfoUpdate(bool changed)
5427 {
5428 if (!changed) {
5429 return;
5430 }
5431 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_TRANSFORM_CHANGE);
5432 if (AnimationUtils::IsImplicitAnimationOpen()) {
5433 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_START_ANIMATION);
5434 }
5435 }
5436
OnNodeTransitionInfoUpdate()5437 void FrameNode::OnNodeTransitionInfoUpdate()
5438 {
5439 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_TRANSITION_START);
5440 }
5441
GetInspectorValue()5442 void FrameNode::GetInspectorValue()
5443 {
5444 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
5445 if (GetTag() == V2::WEB_ETS_TAG) {
5446 UiSessionManager::GetInstance().WebTaskNumsChange(1);
5447 auto pattern = GetPattern<NG::WebPattern>();
5448 CHECK_NULL_VOID(pattern);
5449 auto cb = [](std::shared_ptr<JsonValue> value, int32_t webId) {
5450 UiSessionManager::GetInstance().AddValueForTree(webId, value->ToString());
5451 UiSessionManager::GetInstance().WebTaskNumsChange(-1);
5452 };
5453 pattern->GetAllWebAccessibilityNodeInfos(cb, GetId());
5454 }
5455 #endif
5456 UINode::GetInspectorValue();
5457 }
5458
NotifyWebPattern(bool isRegister)5459 void FrameNode::NotifyWebPattern(bool isRegister)
5460 {
5461 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(WEB_SUPPORTED) && defined(OHOS_PLATFORM)
5462 if (GetTag() == V2::WEB_ETS_TAG) {
5463 auto pattern = GetPattern<NG::WebPattern>();
5464 CHECK_NULL_VOID(pattern);
5465 if (isRegister) {
5466 auto callback = [](int64_t accessibilityId, const std::string data) {
5467 UiSessionManager::GetInstance().ReportWebUnfocusEvent(accessibilityId, data);
5468 };
5469 pattern->RegisterTextBlurCallback(callback);
5470 } else {
5471 pattern->UnRegisterTextBlurCallback();
5472 }
5473 }
5474 #endif
5475 UINode::NotifyWebPattern(isRegister);
5476 }
5477
NotifyChange(int32_t index,int32_t count,int64_t id,NotificationType notificationType)5478 void FrameNode::NotifyChange(int32_t index, int32_t count, int64_t id, NotificationType notificationType)
5479 {
5480 int32_t updateFrom = CalcAbsPosition(index, id);
5481 auto pattern = GetPattern();
5482 switch (notificationType) {
5483 case NotificationType::START_CHANGE_POSITION:
5484 ChildrenUpdatedFrom(updateFrom);
5485 break;
5486 case NotificationType::END_CHANGE_POSITION:
5487 pattern->NotifyDataChange(updateFrom, count);
5488 break;
5489 case NotificationType::START_AND_END_CHANGE_POSITION:
5490 ChildrenUpdatedFrom(updateFrom);
5491 pattern->NotifyDataChange(updateFrom, count);
5492 break;
5493 default:
5494 break;
5495 }
5496 }
5497
5498 // for Grid refresh GridItems
ChildrenUpdatedFrom(int32_t index)5499 void FrameNode::ChildrenUpdatedFrom(int32_t index)
5500 {
5501 childrenUpdatedFrom_ = childrenUpdatedFrom_ >= 0 ? std::min(index, childrenUpdatedFrom_) : index;
5502 }
5503
GetWindowPatternType() const5504 uint32_t FrameNode::GetWindowPatternType() const
5505 {
5506 CHECK_NULL_RETURN(pattern_, 0);
5507 return pattern_->GetWindowPatternType();
5508 }
5509
ResetPredictNodes()5510 void FrameNode::ResetPredictNodes()
5511 {
5512 auto predictLayoutNode = std::move(predictLayoutNode_);
5513 for (auto& node : predictLayoutNode) {
5514 auto frameNode = node.Upgrade();
5515 if (frameNode && frameNode->isLayoutDirtyMarked_) {
5516 frameNode->isLayoutDirtyMarked_ = false;
5517 }
5518 }
5519 }
5520
SetJSCustomProperty(std::function<bool ()> func,std::function<std::string (const std::string &)> getFunc)5521 void FrameNode::SetJSCustomProperty(std::function<bool()> func, std::function<std::string(const std::string&)> getFunc)
5522 {
5523 bool result = func();
5524 if (IsCNode()) {
5525 return;
5526 }
5527 if (result) {
5528 customPropertyMap_[UPDATE_FLAG_KEY] = "1";
5529 }
5530 if (!getCustomProperty_) {
5531 getCustomProperty_ = getFunc;
5532 }
5533 }
5534
GetJSCustomProperty(const std::string & key,std::string & value)5535 bool FrameNode::GetJSCustomProperty(const std::string& key, std::string& value)
5536 {
5537 if (getCustomProperty_) {
5538 value = getCustomProperty_(key);
5539 return true;
5540 }
5541 return false;
5542 }
5543
GetCapiCustomProperty(const std::string & key,std::string & value)5544 bool FrameNode::GetCapiCustomProperty(const std::string& key, std::string& value)
5545 {
5546 if (!IsCNode()) {
5547 return false;
5548 }
5549 auto iter = customPropertyMap_.find(key);
5550 if (iter != customPropertyMap_.end()) {
5551 value = iter->second;
5552 return true;
5553 }
5554 return false;
5555 }
5556
AddCustomProperty(const std::string & key,const std::string & value)5557 void FrameNode::AddCustomProperty(const std::string& key, const std::string& value)
5558 {
5559 customPropertyMap_[key] = value;
5560 }
5561
RemoveCustomProperty(const std::string & key)5562 void FrameNode::RemoveCustomProperty(const std::string& key)
5563 {
5564 auto iter = customPropertyMap_.find(key);
5565 if (iter != customPropertyMap_.end()) {
5566 customPropertyMap_.erase(iter);
5567 }
5568 }
5569 } // namespace OHOS::Ace::NG
5570