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