• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/inspector.h"
17 
18 #include <unistd.h>
19 #include <unordered_set>
20 
21 #include "base/memory/ace_type.h"
22 #include "base/utils/utils.h"
23 #include "core/common/ace_application_info.h"
24 #include "core/common/recorder/event_recorder.h"
25 #include "core/components_ng/base/inspector_filter.h"
26 #include "core/components_ng/base/ui_node.h"
27 #include "core/components_ng/pattern/custom/custom_node.h"
28 #include "core/components_ng/pattern/stage/page_info.h"
29 #include "core/components_ng/pattern/stage/page_pattern.h"
30 #include "core/components_ng/pattern/text/span_node.h"
31 #include "core/components_ng/render/render_context.h"
32 #include "foundation/arkui/ace_engine/frameworks/base/utils/utf.h"
33 
34 namespace OHOS::Ace::NG {
35 namespace {
36 const char INSPECTOR_TYPE[] = "$type";
37 const char INSPECTOR_ID[] = "$ID";
38 const char INSPECTOR_RECT[] = "$rect";
39 const char INSPECTOR_ATTRS[] = "$attrs";
40 const char INSPECTOR_ROOT[] = "root";
41 const char INSPECTOR_PAGE_URL[] = "pageUrl";
42 const char INSPECTOR_NAV_DST_NAME[] = "navDstName";
43 const char INSPECTOR_WIDTH[] = "width";
44 const char INSPECTOR_HEIGHT[] = "height";
45 const char INSPECTOR_RESOLUTION[] = "$resolution";
46 const char INSPECTOR_CHILDREN[] = "$children";
47 const char INSPECTOR_DEBUGLINE[] = "$debugLine";
48 #ifdef PREVIEW
49 const char INSPECTOR_VIEW_ID[] = "$viewID";
50 #else
51 const char INSPECTOR_CUSTOM_VIEW_TAG[] = "viewTag";
52 const char INSPECTOR_COMPONENT_TYPE[] = "type";
53 const char INSPECTOR_STATE_VAR[] = "state";
54 #endif
55 const char INSPECTOR_ATTR_ID[] = "id";
56 const char INSPECTOR_LABEL[] = "label";
57 const char INSPECTOR_CONTENT[] = "content";
58 const char INSPECTOR_ENABLED[] = "enabled";
59 const char INSPECTOR_OPACITY[] = "opacity";
60 const char INSPECTOR_ZINDEX[] = "zindex";
61 const char INSPECTOR_VISIBILITY[] = "visibility";
62 
63 
64 const uint32_t LONG_PRESS_DELAY = 1000;
65 RectF deviceRect;
66 
GetInspectorByKey(const RefPtr<FrameNode> & root,const std::string & key,bool notDetach=false)67 RefPtr<UINode> GetInspectorByKey(const RefPtr<FrameNode>& root, const std::string& key, bool notDetach = false)
68 {
69     std::queue<RefPtr<UINode>> elements;
70     elements.push(root);
71     RefPtr<UINode> inspectorElement;
72     while (!elements.empty()) {
73         auto current = elements.front();
74         elements.pop();
75         if (key == current->GetInspectorId().value_or("")) {
76             return current;
77         }
78 
79         const auto& children = current->GetChildren(notDetach);
80         for (const auto& child : children) {
81             elements.push(child);
82         }
83     }
84     return nullptr;
85 }
86 
DumpElementTree(int32_t depth,const RefPtr<UINode> & element,std::map<int32_t,std::list<RefPtr<UINode>>> & depthElementMap)87 void DumpElementTree(
88     int32_t depth, const RefPtr<UINode>& element, std::map<int32_t, std::list<RefPtr<UINode>>>& depthElementMap)
89 {
90     if (element->GetChildren().empty()) {
91         return;
92     }
93     const auto& children = element->GetChildren();
94     depthElementMap[depth].insert(depthElementMap[depth].end(), children.begin(), children.end());
95     for (const auto& depthElement : children) {
96         DumpElementTree(depth + 1, depthElement, depthElementMap);
97     }
98 }
99 
GetUpPoint(const TouchEvent & downPoint)100 TouchEvent GetUpPoint(const TouchEvent& downPoint)
101 {
102     return TouchEvent {}
103         .SetX(downPoint.x)
104         .SetY(downPoint.y)
105         .SetType(TouchType::UP)
106         .SetTime(std::chrono::high_resolution_clock::now())
107         .SetSourceType(SourceType::TOUCH);
108 }
109 #ifdef PREVIEW
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::vector<RefPtr<NG::UINode>> & children,int32_t pageId,bool isLayoutInspector=false)110 void GetFrameNodeChildren(const RefPtr<NG::UINode>& uiNode, std::vector<RefPtr<NG::UINode>>& children, int32_t pageId,
111     bool isLayoutInspector = false)
112 {
113     // Set ViewId for the fast preview.
114     auto parent = uiNode->GetParent();
115     if (parent && parent->GetTag() == "JsView") {
116         uiNode->SetViewId(std::to_string(parent->GetId()));
117     } else {
118         uiNode->SetViewId(parent->GetViewId());
119     }
120     if (uiNode->GetTag() == "stage") {
121     } else if (uiNode->GetTag() == "page") {
122         if (uiNode->GetPageId() != pageId) {
123             return;
124         }
125     } else {
126         if (!uiNode->GetDebugLine().empty()) {
127             children.emplace_back(uiNode);
128             return;
129         }
130     }
131 
132     for (const auto& frameChild : uiNode->GetChildren()) {
133         GetFrameNodeChildren(frameChild, children, pageId);
134     }
135 }
136 
GetSpanInspector(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId)137 void GetSpanInspector(
138     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId)
139 {
140     // span rect follows parent text size
141     auto spanParentNode = parent->GetParent();
142     while (spanParentNode != nullptr) {
143         if (AceType::InstanceOf<NG::FrameNode>(spanParentNode)) {
144             break;
145         }
146         spanParentNode = spanParentNode->GetParent();
147     }
148     CHECK_NULL_VOID(spanParentNode);
149     auto node = AceType::DynamicCast<FrameNode>(spanParentNode);
150     auto jsonNode = JsonUtil::Create(true);
151     auto jsonObject = JsonUtil::Create(true);
152 
153     InspectorFilter filter;
154     parent->ToJsonValue(jsonObject, filter);
155     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
156     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
157     jsonNode->Put(INSPECTOR_ID, parent->GetId());
158     RectF rect = node->GetTransformRectRelativeToWindow();
159     rect = rect.Constrain(deviceRect);
160     if (rect.IsEmpty()) {
161         rect.SetRect(0, 0, 0, 0);
162     }
163     auto strRec = std::to_string(rect.Left())
164                       .append(",")
165                       .append(std::to_string(rect.Top()))
166                       .append(",")
167                       .append(std::to_string(rect.Width()))
168                       .append(",")
169                       .append(std::to_string(rect.Height()));
170     jsonNode->Put(INSPECTOR_RECT, strRec.c_str());
171     jsonNode->Put(INSPECTOR_DEBUGLINE, parent->GetDebugLine().c_str());
172     jsonNode->Put(INSPECTOR_VIEW_ID, parent->GetViewId().c_str());
173     jsonNodeArray->PutRef(std::move(jsonNode));
174 }
175 
GetInspectorChildren(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId,bool isActive,const InspectorFilter & filter=InspectorFilter (),uint32_t depth=UINT32_MAX,bool isLayoutInspector=false)176 void GetInspectorChildren(const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray,
177     int pageId, bool isActive, const InspectorFilter& filter = InspectorFilter(), uint32_t depth = UINT32_MAX,
178     bool isLayoutInspector = false)
179 {
180     // Span is a special case in Inspector since span inherits from UINode
181     if (AceType::InstanceOf<SpanNode>(parent)) {
182         GetSpanInspector(parent, jsonNodeArray, pageId);
183         return;
184     }
185     auto jsonNode = JsonUtil::Create(true);
186     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
187     jsonNode->Put(INSPECTOR_ID, parent->GetId());
188     auto node = AceType::DynamicCast<FrameNode>(parent);
189     if (node) {
190         RectF rect;
191         isActive = isActive && node->IsActive();
192         if (isActive) {
193             rect = node->GetTransformRectRelativeToWindow();
194         }
195         rect = rect.Constrain(deviceRect);
196         if (rect.IsEmpty()) {
197             rect.SetRect(0, 0, 0, 0);
198         }
199         auto strRec = std::to_string(rect.Left()).append(",")
200                           .append(std::to_string(rect.Top())).append(",")
201                           .append(std::to_string(rect.Width())).append(",")
202                           .append(std::to_string(rect.Height()));
203         jsonNode->Put(INSPECTOR_RECT, strRec.c_str());
204         jsonNode->Put(INSPECTOR_DEBUGLINE, node->GetDebugLine().c_str());
205         jsonNode->Put(INSPECTOR_VIEW_ID, node->GetViewId().c_str());
206         auto jsonObject = JsonUtil::Create(true);
207 
208         InspectorFilter filter;
209         parent->ToJsonValue(jsonObject, filter);
210         jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
211     }
212 
213     std::vector<RefPtr<NG::UINode>> children;
214     for (const auto& item : parent->GetChildren()) {
215         GetFrameNodeChildren(item, children, pageId);
216     }
217     if (node != nullptr) {
218         auto overlayNode = node->GetOverlayNode();
219         if (overlayNode != nullptr) {
220             GetFrameNodeChildren(overlayNode, children, pageId);
221         }
222     }
223     if (depth) {
224         auto jsonChildrenArray = JsonUtil::CreateArray(true);
225         for (auto uiNode : children) {
226             GetInspectorChildren(uiNode, jsonChildrenArray, pageId, isActive, filter, depth - 1);
227         }
228         if (jsonChildrenArray->GetArraySize()) {
229             jsonNode->PutRef(INSPECTOR_CHILDREN, std::move(jsonChildrenArray));
230         }
231     }
232     jsonNodeArray->PutRef(std::move(jsonNode));
233 }
234 
235 #else
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::vector<RefPtr<NG::UINode>> & children,int32_t pageId,bool isLayoutInspector=false)236 void GetFrameNodeChildren(const RefPtr<NG::UINode>& uiNode, std::vector<RefPtr<NG::UINode>>& children,
237     int32_t pageId, bool isLayoutInspector = false)
238 {
239     if (AceType::InstanceOf<NG::FrameNode>(uiNode) || AceType::InstanceOf<SpanNode>(uiNode) ||
240         AceType::InstanceOf<CustomNode>(uiNode)) {
241         if (uiNode->GetTag() == "stage") {
242         } else if (uiNode->GetTag() == "page") {
243             if (uiNode->GetPageId() != pageId) {
244                 return;
245             }
246         } else {
247             auto custom = AceType::DynamicCast<NG::CustomNode>(uiNode);
248             auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
249             auto spanNode = AceType::DynamicCast<NG::SpanNode>(uiNode);
250             if ((frameNode && !frameNode->IsInternal()) || spanNode || (custom && isLayoutInspector)) {
251                 children.emplace_back(uiNode);
252                 return;
253             }
254         }
255     }
256     for (const auto& frameChild : uiNode->GetChildren()) {
257         GetFrameNodeChildren(frameChild, children, pageId, isLayoutInspector);
258     }
259 }
260 
GetSpanInspector(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId)261 void GetSpanInspector(
262     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId)
263 {
264     // span rect follows parent text size
265     auto spanParentNode = parent->GetParent();
266     while (spanParentNode != nullptr) {
267         if (AceType::InstanceOf<NG::FrameNode>(spanParentNode)) {
268             break;
269         }
270         spanParentNode = spanParentNode->GetParent();
271     }
272     CHECK_NULL_VOID(spanParentNode);
273     auto node = AceType::DynamicCast<FrameNode>(spanParentNode);
274     auto jsonNode = JsonUtil::Create(true);
275     auto jsonObject = JsonUtil::Create(true);
276 
277     InspectorFilter filter;
278     parent->ToJsonValue(jsonObject, filter);
279     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
280     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
281     jsonNode->Put(INSPECTOR_ID, parent->GetId());
282     jsonNode->Put(INSPECTOR_DEBUGLINE, parent->GetDebugLine().c_str());
283     RectF rect = node->GetTransformRectRelativeToWindow();
284     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
285     jsonNodeArray->PutRef(std::move(jsonNode));
286 }
287 
GetCustomNodeInfo(const RefPtr<NG::UINode> & customNode,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNode)288 void GetCustomNodeInfo(const RefPtr<NG::UINode> &customNode, std::unique_ptr<OHOS::Ace::JsonValue> &jsonNode)
289 {
290     // custom node rect follows parent size
291     auto hostNode = customNode->GetParent();
292     while (hostNode != nullptr) {
293         if (AceType::InstanceOf<NG::FrameNode>(hostNode)) {
294             break;
295         }
296         hostNode = hostNode->GetParent();
297     }
298     CHECK_NULL_VOID(hostNode);
299     jsonNode->Put(INSPECTOR_COMPONENT_TYPE, "custom");
300     auto node = AceType::DynamicCast<CustomNode>(customNode);
301     CHECK_NULL_VOID(node);
302     auto parentNode = AceType::DynamicCast<FrameNode>(hostNode);
303     jsonNode->Put(INSPECTOR_STATE_VAR, node->GetStateInspectorInfo());
304     RectF rect = parentNode->GetTransformRectRelativeToWindow();
305     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
306     jsonNode->Put(INSPECTOR_DEBUGLINE, customNode->GetDebugLine().c_str());
307     jsonNode->Put(INSPECTOR_CUSTOM_VIEW_TAG, node->GetCustomTag().c_str());
308 }
309 
GetInspectorChildren(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId,bool isActive,const InspectorFilter & filter=InspectorFilter (),uint32_t depth=UINT32_MAX,bool isLayoutInspector=false)310 void GetInspectorChildren(const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray,
311     int pageId, bool isActive, const InspectorFilter& filter = InspectorFilter(), uint32_t depth = UINT32_MAX,
312     bool isLayoutInspector = false)
313 {
314     // Span is a special case in Inspector since span inherits from UINode
315     if (AceType::InstanceOf<SpanNode>(parent)) {
316         GetSpanInspector(parent, jsonNodeArray, pageId);
317         return;
318     }
319     if (AceType::InstanceOf<CustomNode>(parent) && !isLayoutInspector) {
320         return;
321     }
322     auto jsonNode = JsonUtil::Create(true);
323     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
324     jsonNode->Put(INSPECTOR_ID, parent->GetId());
325     if (parent->GetTag() == V2::JS_VIEW_ETS_TAG) {
326         GetCustomNodeInfo(parent, jsonNode);
327     } else {
328         jsonNode->Put(INSPECTOR_COMPONENT_TYPE, "build-in");
329     }
330     auto node = AceType::DynamicCast<FrameNode>(parent);
331     if (node) {
332         RectF rect;
333         isActive = isActive && node->IsActive();
334         if (isActive) {
335             rect = node->GetTransformRectRelativeToWindow();
336         }
337         jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
338         jsonNode->Put(INSPECTOR_DEBUGLINE, node->GetDebugLine().c_str());
339     }
340     auto jsonObject = JsonUtil::Create(true);
341     parent->ToJsonValue(jsonObject, filter);
342     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
343     std::string jsonNodeStr = jsonNode->ToString();
344     ConvertIllegalStr(jsonNodeStr);
345     auto jsonNodeNew = JsonUtil::ParseJsonString(jsonNodeStr);
346     std::vector<RefPtr<NG::UINode>> children;
347     for (const auto& item : parent->GetChildren()) {
348         GetFrameNodeChildren(item, children, pageId, isLayoutInspector);
349     }
350     if (node) {
351         auto overlayNode = node->GetOverlayNode();
352         if (overlayNode != nullptr) {
353             GetFrameNodeChildren(overlayNode, children, pageId, isLayoutInspector);
354         }
355     }
356     if (depth) {
357         auto jsonChildrenArray = JsonUtil::CreateArray(true);
358         for (auto uiNode : children) {
359             GetInspectorChildren(uiNode, jsonChildrenArray, pageId, isActive, filter, depth - 1, isLayoutInspector);
360         }
361         if (jsonChildrenArray->GetArraySize()) {
362             jsonNodeNew->PutRef(INSPECTOR_CHILDREN, std::move(jsonChildrenArray));
363         }
364     }
365     jsonNodeArray->PutRef(std::move(jsonNodeNew));
366 }
367 #endif
368 
GetOverlayNode(const RefPtr<NG::UINode> & pageNode)369 RefPtr<NG::UINode> GetOverlayNode(const RefPtr<NG::UINode>& pageNode)
370 {
371     CHECK_NULL_RETURN(pageNode, nullptr);
372     auto stageNode = pageNode->GetParent();
373     CHECK_NULL_RETURN(stageNode, nullptr);
374     auto stageParent = stageNode->GetParent();
375     CHECK_NULL_RETURN(stageParent, nullptr);
376     auto overlayNode = stageParent->GetChildren().back();
377     if (overlayNode->GetTag() == "stage") {
378         return nullptr;
379     }
380     return overlayNode;
381 }
382 
GetContextInfo(const RefPtr<PipelineContext> & context,std::unique_ptr<JsonValue> & jsonRoot)383 void GetContextInfo(const RefPtr<PipelineContext>& context, std::unique_ptr<JsonValue>& jsonRoot)
384 {
385     auto scale = context->GetViewScale();
386     auto rootHeight = context->GetRootHeight();
387     auto rootWidth = context->GetRootWidth();
388     deviceRect.SetRect(0, 0, rootWidth * scale, rootHeight * scale);
389     jsonRoot->Put(INSPECTOR_WIDTH, std::to_string(rootWidth * scale).c_str());
390     jsonRoot->Put(INSPECTOR_HEIGHT, std::to_string(rootHeight * scale).c_str());
391     jsonRoot->Put(INSPECTOR_RESOLUTION, std::to_string(PipelineBase::GetCurrentDensity()).c_str());
392 }
393 
GetInspectorInfo(std::vector<RefPtr<NG::UINode>> children,int32_t pageId,std::unique_ptr<JsonValue> jsonRoot,bool isLayoutInspector,const InspectorFilter & filter=InspectorFilter ())394 std::string GetInspectorInfo(std::vector<RefPtr<NG::UINode>> children, int32_t pageId,
395     std::unique_ptr<JsonValue> jsonRoot, bool isLayoutInspector, const InspectorFilter& filter = InspectorFilter())
396 {
397     auto jsonNodeArray = JsonUtil::CreateArray(true);
398     auto depth = filter.GetFilterDepth();
399     for (auto& uiNode : children) {
400         GetInspectorChildren(uiNode, jsonNodeArray, pageId, true, filter, depth - 1, isLayoutInspector);
401     }
402     if (jsonNodeArray->GetArraySize()) {
403         jsonRoot->PutRef(INSPECTOR_CHILDREN, std::move(jsonNodeArray));
404     }
405 
406     if (isLayoutInspector) {
407         auto jsonTree = JsonUtil::Create(true);
408         jsonTree->Put("type", "root");
409         jsonTree->PutRef("content", std::move(jsonRoot));
410         auto pipeline = PipelineContext::GetCurrentContextSafely();
411         if (pipeline) {
412             jsonTree->Put("VsyncID", (int32_t)pipeline->GetFrameCount());
413             jsonTree->Put("ProcessID", getpid());
414             jsonTree->Put("WindowID", (int32_t)pipeline->GetWindowId());
415         }
416         return jsonTree->ToString();
417     }
418 
419     return jsonRoot->ToString();
420 }
421 } // namespace
422 
423 std::set<RefPtr<FrameNode>> Inspector::offscreenNodes;
424 
GetFrameNodeByKey(const std::string & key,bool notDetach)425 RefPtr<FrameNode> Inspector::GetFrameNodeByKey(const std::string& key, bool notDetach)
426 {
427     if (!offscreenNodes.empty()) {
428         for (auto node : offscreenNodes) {
429             auto frameNode = AceType::DynamicCast<FrameNode>(GetInspectorByKey(node, key, notDetach));
430             if (frameNode) {
431                 return frameNode;
432             }
433         }
434     }
435     auto context = NG::PipelineContext::GetCurrentContext();
436     if (!context) {
437         LOGW("Internal error! Context is null. key: %{public}s", key.c_str());
438         return nullptr;
439     }
440     auto rootNode = context->GetRootElement();
441     if (!rootNode) {
442         LOGW("Internal error! RootNode is null. key: %{public}s", key.c_str());
443         return nullptr;
444     }
445 
446     return AceType::DynamicCast<FrameNode>(GetInspectorByKey(rootNode, key, notDetach));
447 }
448 
GetInspectorNodeByKey(const std::string & key,const InspectorFilter & filter)449 std::string Inspector::GetInspectorNodeByKey(const std::string& key, const InspectorFilter& filter)
450 {
451     auto context = NG::PipelineContext::GetCurrentContext();
452     CHECK_NULL_RETURN(context, "");
453     auto rootNode = context->GetRootElement();
454     CHECK_NULL_RETURN(rootNode, "");
455 
456     auto inspectorElement = GetInspectorByKey(rootNode, key);
457     CHECK_NULL_RETURN(inspectorElement, "");
458 
459     auto jsonNode = JsonUtil::Create(true);
460     jsonNode->Put(INSPECTOR_TYPE, inspectorElement->GetTag().c_str());
461     jsonNode->Put(INSPECTOR_ID, inspectorElement->GetId());
462     auto frameNode = AceType::DynamicCast<FrameNode>(inspectorElement);
463     if (frameNode) {
464         auto rect = frameNode->GetTransformRectRelativeToWindow();
465         jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
466     }
467     auto jsonAttrs = JsonUtil::Create(true);
468     std::string debugLine = inspectorElement->GetDebugLine();
469     jsonNode->Put(INSPECTOR_DEBUGLINE, debugLine.c_str());
470 
471     inspectorElement->ToJsonValue(jsonAttrs, filter);
472     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonAttrs));
473     return jsonNode->ToString();
474 }
475 
GetRectangleById(const std::string & key,Rectangle & rectangle)476 void Inspector::GetRectangleById(const std::string& key, Rectangle& rectangle)
477 {
478     auto frameNode = Inspector::GetFrameNodeByKey(key, true);
479     if (!frameNode) {
480         LOGW("Can't find component:%{public}s, check your parameters", key.c_str());
481         return;
482     }
483     rectangle.size = frameNode->GetGeometryNode()->GetFrameSize();
484     auto context = frameNode->GetRenderContext();
485     if (!context) {
486         LOGW("Internal error! Component(id=%{public}s) is null", key.c_str());
487         return;
488     }
489     rectangle.localOffset = context->GetPaintRectWithTransform().GetOffset();
490     rectangle.windowOffset = frameNode->GetOffsetRelativeToWindow();
491     auto pipeline = frameNode->GetContext();
492     CHECK_NULL_VOID(pipeline);
493     rectangle.screenRect = pipeline->GetCurrentWindowRect();
494     ACE_SCOPED_TRACE("Inspector::GetRectangleById_Id=%d_Tag=%s_Key=%s",
495         frameNode->GetId(), frameNode->GetTag().c_str(), key.c_str());
496     LOGI("GetRectangleById Id:%{public}d key:%{public}s tag:%{public}s localOffset:%{public}s"
497          " windowOffset:%{public}s screenRect:%{public}s",
498         frameNode->GetId(), key.c_str(), frameNode->GetTag().c_str(), rectangle.localOffset.ToString().c_str(),
499         rectangle.windowOffset.ToString().c_str(), rectangle.screenRect.ToString().c_str());
500     auto renderContext = frameNode->GetRenderContext();
501     CHECK_NULL_VOID(renderContext);
502     Matrix4 defMatrix4 = Matrix4::CreateIdentity();
503     Matrix4 matrix4 = renderContext->GetTransformMatrixValue(defMatrix4);
504     rectangle.matrix4 = matrix4;
505     auto rect = renderContext->GetPaintRectWithoutTransform();
506     const double halfDimension = 50.0;
507     auto center = renderContext->GetTransformCenter().value_or(DimensionOffset(
508         Dimension(halfDimension, DimensionUnit::PERCENT), Dimension(halfDimension, DimensionUnit::PERCENT)));
509     double centerX = 0.0;
510     double centerY = 0.0;
511     if (center.GetX().Unit() == DimensionUnit::PERCENT || center.GetY().Unit() == DimensionUnit::PERCENT) {
512         if (rect.IsValid()) {
513             centerX = Dimension(center.GetX().ConvertToPxWithSize(rect.Width()), DimensionUnit::PX).ConvertToVp();
514             centerY = Dimension(center.GetY().ConvertToPxWithSize(rect.Height()), DimensionUnit::PX).ConvertToVp();
515         }
516     } else {
517         centerX = center.GetX().ConvertToVp();
518         centerY = center.GetY().ConvertToVp();
519     }
520     VectorF defScale = VectorF(1.0, 1.0);
521     VectorF scale = renderContext->GetTransformScaleValue(defScale);
522     rectangle.scale.x = scale.x;
523     rectangle.scale.y = scale.y;
524     rectangle.scale.z = 1.0;
525     rectangle.scale.centerX = centerX;
526     rectangle.scale.centerY = centerY;
527     Vector5F defRotate = Vector5F(0.0, 0.0, 0.0, 0.0, 0.0);
528     Vector5F rotate = renderContext->GetTransformRotateValue(defRotate);
529     rectangle.rotate.x = rotate.x;
530     rectangle.rotate.y = rotate.y;
531     rectangle.rotate.z = rotate.z;
532     rectangle.rotate.angle = rotate.w;
533     rectangle.rotate.centerX = centerX;
534     rectangle.rotate.centerY = centerY;
535     TranslateOptions defTranslate = TranslateOptions(0.0, 0.0, 0.0);
536     TranslateOptions translate = renderContext->GetTransformTranslateValue(defTranslate);
537     if ((translate.x.Unit() == DimensionUnit::PERCENT) && rect.IsValid()) {
538         rectangle.translate.x =
539             Dimension(translate.x.ConvertToPxWithSize(rect.Width()), DimensionUnit::PX).ConvertToVp();
540     } else {
541         rectangle.translate.x = translate.x.ConvertToVp();
542     }
543     if ((translate.y.Unit() == DimensionUnit::PERCENT) && rect.IsValid()) {
544         rectangle.translate.y =
545             Dimension(translate.y.ConvertToPxWithSize(rect.Height()), DimensionUnit::PX).ConvertToVp();
546     } else {
547         rectangle.translate.y = translate.y.ConvertToVp();
548     }
549     rectangle.translate.z = translate.z.ConvertToVp();
550 }
551 
GetInspector(bool isLayoutInspector)552 std::string Inspector::GetInspector(bool isLayoutInspector)
553 {
554     InspectorFilter filter;
555     bool needThrow = false;
556     return GetInspector(isLayoutInspector, filter, needThrow);
557 }
558 
GetInspector(bool isLayoutInspector,const InspectorFilter & filter,bool & needThrow)559 std::string Inspector::GetInspector(bool isLayoutInspector, const InspectorFilter& filter, bool& needThrow)
560 {
561     auto jsonRoot = JsonUtil::Create(true);
562     jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
563     needThrow = false;
564     auto context = NG::PipelineContext::GetCurrentContext();
565     if (context == nullptr) {
566         needThrow = true;
567         return jsonRoot->ToString();
568     }
569     GetContextInfo(context, jsonRoot);
570 
571     RefPtr<UINode> pageRootNode;
572     const std::string key = filter.GetFilterID();
573     if (key.empty()) {
574         pageRootNode = context->GetStageManager()->GetLastPage();
575     } else {
576         auto rootNode = context->GetStageManager()->GetLastPage();
577         if (rootNode == nullptr) {
578             needThrow = true;
579             return jsonRoot->ToString();
580         }
581         pageRootNode = GetInspectorByKey(rootNode, key);
582     }
583     if (pageRootNode == nullptr) {
584         needThrow = true;
585         return jsonRoot->ToString();
586     }
587     auto pageId = context->GetStageManager()->GetLastPage()->GetPageId();
588     std::vector<RefPtr<NG::UINode>> children;
589     if (key.empty()) {
590         for (const auto& item : pageRootNode->GetChildren()) {
591             GetFrameNodeChildren(item, children, pageId, isLayoutInspector);
592         }
593         auto overlayNode = GetOverlayNode(pageRootNode);
594         if (overlayNode) {
595             GetFrameNodeChildren(overlayNode, children, pageId, isLayoutInspector);
596         }
597     } else {
598         children.emplace_back(pageRootNode);
599     }
600     return GetInspectorInfo(children, pageId, std::move(jsonRoot), isLayoutInspector, filter);
601 }
602 
GetInspectorOfNode(RefPtr<NG::UINode> node)603 std::string Inspector::GetInspectorOfNode(RefPtr<NG::UINode> node)
604 {
605     auto jsonRoot = JsonUtil::Create(true);
606 
607     auto context = NG::PipelineContext::GetCurrentContext();
608     CHECK_NULL_RETURN(context, jsonRoot->ToString());
609     GetContextInfo(context, jsonRoot);
610     CHECK_NULL_RETURN(node, jsonRoot->ToString());
611     auto pageId = context->GetStageManager()->GetLastPage()->GetPageId();
612     auto jsonNodeArray = JsonUtil::CreateArray(true);
613     GetInspectorChildren(node, jsonNodeArray, pageId, true, InspectorFilter(), 0);
614     if (jsonNodeArray->GetArraySize()) {
615         jsonRoot = jsonNodeArray->GetArrayItem(0);
616         GetContextInfo(context, jsonRoot);
617     }
618 
619     return jsonRoot->ToString();
620 }
621 
GetSubWindowInspector(bool isLayoutInspector)622 std::string Inspector::GetSubWindowInspector(bool isLayoutInspector)
623 {
624     auto jsonRoot = JsonUtil::Create(true);
625     jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
626 
627     auto context = NG::PipelineContext::GetCurrentContext();
628     CHECK_NULL_RETURN(context, jsonRoot->ToString());
629     GetContextInfo(context, jsonRoot);
630     auto overlayNode = context->GetOverlayManager()->GetRootNode().Upgrade();
631     CHECK_NULL_RETURN(overlayNode, jsonRoot->ToString());
632     auto pageId = 0;
633     std::vector<RefPtr<NG::UINode>> children;
634     GetFrameNodeChildren(overlayNode, children, pageId, isLayoutInspector);
635 
636     return GetInspectorInfo(children, 0, std::move(jsonRoot), isLayoutInspector);
637 }
638 
FillSimplifiedInspectorAttrs(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNode)639 void FillSimplifiedInspectorAttrs(const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNode)
640 {
641     auto tmpJson = JsonUtil::Create(true);
642 
643     InspectorFilter filter;
644     parent->ToJsonValue(tmpJson, filter);
645     jsonNode->Put(INSPECTOR_ATTR_ID, tmpJson->GetString(INSPECTOR_ATTR_ID).c_str());
646 
647     auto jsonObject = JsonUtil::Create(true);
648     if (tmpJson->Contains(INSPECTOR_LABEL)) {
649         jsonObject->Put(INSPECTOR_LABEL, tmpJson->GetString(INSPECTOR_LABEL).c_str());
650     }
651     if (tmpJson->Contains(INSPECTOR_CONTENT)) {
652         jsonObject->Put(INSPECTOR_CONTENT, tmpJson->GetString(INSPECTOR_CONTENT).c_str());
653     }
654     jsonObject->Put(INSPECTOR_ENABLED, tmpJson->GetBool(INSPECTOR_ENABLED));
655     jsonObject->Put(INSPECTOR_OPACITY, tmpJson->GetDouble(INSPECTOR_OPACITY));
656     jsonObject->Put(INSPECTOR_ZINDEX, tmpJson->GetInt(INSPECTOR_ZINDEX));
657     jsonObject->Put(INSPECTOR_VISIBILITY, tmpJson->GetString(INSPECTOR_VISIBILITY).c_str());
658     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
659 }
660 
GetSimplifiedSpanInspector(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId)661 void GetSimplifiedSpanInspector(
662     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId)
663 {
664     // span rect follows parent text size
665     auto spanParentNode = parent->GetParent();
666     CHECK_NULL_VOID(spanParentNode);
667     auto node = AceType::DynamicCast<FrameNode>(spanParentNode);
668     CHECK_NULL_VOID(node);
669     auto jsonNode = JsonUtil::Create(true);
670 
671     FillSimplifiedInspectorAttrs(parent, jsonNode);
672 
673     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
674     RectF rect = node->GetTransformRectRelativeToWindow();
675     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
676     jsonNodeArray->PutRef(std::move(jsonNode));
677 }
678 
GetSimplifiedInspectorChildren(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId,bool isActive)679 void GetSimplifiedInspectorChildren(
680     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId, bool isActive)
681 {
682     // Span is a special case in Inspector since span inherits from UINode
683     if (AceType::InstanceOf<SpanNode>(parent)) {
684         GetSimplifiedSpanInspector(parent, jsonNodeArray, pageId);
685         return;
686     }
687     auto jsonNode = JsonUtil::Create(true);
688     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
689     auto node = AceType::DynamicCast<FrameNode>(parent);
690 
691     RectF rect;
692     isActive = isActive && node->IsActive();
693     if (isActive) {
694         rect = node->GetTransformRectRelativeToWindow();
695     }
696 
697     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
698 
699     FillSimplifiedInspectorAttrs(parent, jsonNode);
700 
701     std::vector<RefPtr<NG::UINode>> children;
702     for (const auto& item : parent->GetChildren()) {
703         GetFrameNodeChildren(item, children, pageId);
704     }
705     auto jsonChildrenArray = JsonUtil::CreateArray(true);
706     for (auto uiNode : children) {
707         GetSimplifiedInspectorChildren(uiNode, jsonChildrenArray, pageId, isActive);
708     }
709     if (jsonChildrenArray->GetArraySize()) {
710         jsonNode->PutRef(INSPECTOR_CHILDREN, std::move(jsonChildrenArray));
711     }
712     jsonNodeArray->PutRef(std::move(jsonNode));
713 }
714 
GetSimplifiedInspector(int32_t containerId)715 std::string Inspector::GetSimplifiedInspector(int32_t containerId)
716 {
717     TAG_LOGI(AceLogTag::ACE_UIEVENT, "GetSimplifiedInspector start: container %{public}d", containerId);
718     auto jsonRoot = JsonUtil::Create(true);
719     jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
720 
721     auto context = NG::PipelineContext::GetContextByContainerId(containerId);
722     CHECK_NULL_RETURN(context, jsonRoot->ToString());
723     auto scale = context->GetViewScale();
724     auto rootHeight = context->GetRootHeight();
725     auto rootWidth = context->GetRootWidth();
726     deviceRect.SetRect(0, 0, rootWidth * scale, rootHeight * scale);
727     jsonRoot->Put(INSPECTOR_WIDTH, std::to_string(rootWidth * scale).c_str());
728     jsonRoot->Put(INSPECTOR_HEIGHT, std::to_string(rootHeight * scale).c_str());
729     jsonRoot->Put(INSPECTOR_RESOLUTION, std::to_string(SystemProperties::GetResolution()).c_str());
730 
731     auto pageRootNode = context->GetStageManager()->GetLastPage();
732     CHECK_NULL_RETURN(pageRootNode, jsonRoot->ToString());
733 
734     auto pagePattern = pageRootNode->GetPattern<PagePattern>();
735     CHECK_NULL_RETURN(pagePattern, jsonRoot->ToString());
736     auto pageInfo = pagePattern->GetPageInfo();
737     CHECK_NULL_RETURN(pageInfo, jsonRoot->ToString());
738     jsonRoot->Put(INSPECTOR_PAGE_URL, pageInfo->GetPageUrl().c_str());
739     jsonRoot->Put(INSPECTOR_NAV_DST_NAME, Recorder::EventRecorder::Get().GetNavDstName().c_str());
740 
741     auto pageId = context->GetStageManager()->GetLastPage()->GetPageId();
742     std::vector<RefPtr<NG::UINode>> children;
743     for (const auto& item : pageRootNode->GetChildren()) {
744         GetFrameNodeChildren(item, children, pageId);
745     }
746     auto overlayNode = GetOverlayNode(pageRootNode);
747     if (overlayNode) {
748         GetFrameNodeChildren(overlayNode, children, pageId);
749     }
750     auto jsonNodeArray = JsonUtil::CreateArray(true);
751     for (auto& uiNode : children) {
752         GetSimplifiedInspectorChildren(uiNode, jsonNodeArray, pageId, true);
753     }
754     if (jsonNodeArray->GetArraySize()) {
755         jsonRoot->PutRef(INSPECTOR_CHILDREN, std::move(jsonNodeArray));
756     }
757 
758     return jsonRoot->ToString();
759 }
760 
SendEventByKey(const std::string & key,int action,const std::string & params)761 bool Inspector::SendEventByKey(const std::string& key, int action, const std::string& params)
762 {
763     auto context = NG::PipelineContext::GetCurrentContext();
764     CHECK_NULL_RETURN(context, false);
765     auto rootNode = context->GetRootElement();
766     CHECK_NULL_RETURN(rootNode, false);
767 
768     auto inspectorElement = AceType::DynamicCast<FrameNode>(GetInspectorByKey(rootNode, key));
769     CHECK_NULL_RETURN(inspectorElement, false);
770 
771     auto size = inspectorElement->GetGeometryNode()->GetFrameSize();
772     auto offset = inspectorElement->GetTransformRelativeOffset();
773     Rect rect { offset.GetX(), offset.GetY(), size.Width(), size.Height() };
774     context->GetTaskExecutor()->PostTask(
775         [weak = AceType::WeakClaim(AceType::RawPtr(context)), rect, action, params]() {
776             auto context = weak.Upgrade();
777             if (!context) {
778                 return;
779             }
780             TouchEvent point;
781             point.SetX(static_cast<float>(rect.Left() + rect.Width() / 2))
782                 .SetY(static_cast<float>(rect.Top() + rect.Height() / 2))
783                 .SetType(TouchType::DOWN)
784                 .SetTime(std::chrono::high_resolution_clock::now())
785                 .SetSourceType(SourceType::TOUCH);
786             context->OnTouchEvent(point.UpdatePointers());
787 
788             switch (action) {
789                 case static_cast<int>(AceAction::ACTION_CLICK): {
790                     context->OnTouchEvent(GetUpPoint(point).UpdatePointers());
791                     break;
792                 }
793                 case static_cast<int>(AceAction::ACTION_LONG_CLICK): {
794                     CancelableCallback<void()> inspectorTimer;
795                     auto&& callback = [weak, point]() {
796                         auto refPtr = weak.Upgrade();
797                         if (refPtr) {
798                             refPtr->OnTouchEvent(GetUpPoint(point).UpdatePointers());
799                         }
800                     };
801                     inspectorTimer.Reset(callback);
802                     auto taskExecutor =
803                         SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
804                     taskExecutor.PostDelayedTask(inspectorTimer, LONG_PRESS_DELAY, "ArkUIInspectorLongPressTouchEvent");
805                     break;
806                 }
807                 default:
808                     break;
809             }
810         },
811         TaskExecutor::TaskType::UI, "ArkUIInspectorSendEventByKey");
812 
813     return true;
814 }
815 
HideAllMenus()816 void Inspector::HideAllMenus()
817 {
818     auto context = NG::PipelineContext::GetCurrentContext();
819     CHECK_NULL_VOID(context);
820     auto overlayManager = context->GetOverlayManager();
821     CHECK_NULL_VOID(overlayManager);
822     overlayManager->HideAllMenus();
823 }
824 
AddOffscreenNode(RefPtr<FrameNode> node)825 void Inspector::AddOffscreenNode(RefPtr<FrameNode> node)
826 {
827     CHECK_NULL_VOID(node);
828     offscreenNodes.insert(node);
829 }
830 
RemoveOffscreenNode(RefPtr<FrameNode> node)831 void Inspector::RemoveOffscreenNode(RefPtr<FrameNode> node)
832 {
833     CHECK_NULL_VOID(node);
834     offscreenNodes.erase(node);
835 }
836 
GetInspectorTree(InspectorTreeMap & treesInfo)837 void Inspector::GetInspectorTree(InspectorTreeMap& treesInfo)
838 {
839     treesInfo.clear();
840     auto context = NG::PipelineContext::GetCurrentContext();
841     CHECK_NULL_VOID(context);
842     auto stageManager = context->GetStageManager();
843     CHECK_NULL_VOID(stageManager);
844     RefPtr<UINode> pageRootNode = stageManager->GetLastPage();
845     CHECK_NULL_VOID(pageRootNode);
846     auto rootNode = AddInspectorTreeNode(pageRootNode, treesInfo);
847     CHECK_NULL_VOID(rootNode);
848     auto pageId = pageRootNode->GetPageId();
849     std::vector<RefPtr<NG::UINode>> children;
850     for (const auto& item : pageRootNode->GetChildren()) {
851         GetFrameNodeChildren(item, children, pageId, false);
852     }
853     auto overlayNode = GetOverlayNode(pageRootNode);
854     if (overlayNode) {
855         GetFrameNodeChildren(overlayNode, children, pageId, false);
856     }
857     return GetInspectorTreeInfo(children, pageId, treesInfo);
858 }
859 
RecordOnePageNodes(const RefPtr<NG::UINode> & pageNode,InspectorTreeMap & treesInfo)860 void Inspector::RecordOnePageNodes(const RefPtr<NG::UINode>& pageNode, InspectorTreeMap& treesInfo)
861 {
862     CHECK_NULL_VOID(pageNode);
863     std::vector<RefPtr<NG::UINode>> children;
864     auto pageId = pageNode->GetPageId();
865     auto rootNode = AddInspectorTreeNode(pageNode, treesInfo);
866     CHECK_NULL_VOID(rootNode);
867     for (const auto& item : pageNode->GetChildren()) {
868         GetFrameNodeChildren(item, children, pageId, false);
869     }
870     auto overlayNode = GetOverlayNode(pageNode);
871     if (overlayNode) {
872         GetFrameNodeChildren(overlayNode, children, pageId, false);
873     }
874     GetInspectorTreeInfo(children, pageId, treesInfo);
875 }
876 
GetRecordAllPagesNodes(InspectorTreeMap & treesInfo)877 void Inspector::GetRecordAllPagesNodes(InspectorTreeMap& treesInfo)
878 {
879     treesInfo.clear();
880     auto context = NG::PipelineContext::GetCurrentContext();
881     CHECK_NULL_VOID(context);
882     auto stageManager = context->GetStageManager();
883     CHECK_NULL_VOID(stageManager);
884     auto stageNode = stageManager->GetStageNode();
885     CHECK_NULL_VOID(stageNode);
886     for (const auto& item : stageNode->GetChildren()) {
887         auto frameNode = AceType::DynamicCast<FrameNode>(item);
888         if (frameNode == nullptr) {
889             continue;
890         }
891         auto pagePattern = frameNode->GetPattern<PagePattern>();
892         if (pagePattern == nullptr) {
893             continue;
894         }
895         RecordOnePageNodes(item, treesInfo);
896     }
897 }
898 
AddInspectorTreeNode(const RefPtr<NG::UINode> & uiNode,InspectorTreeMap & recNodes)899 RefPtr<RecNode> Inspector::AddInspectorTreeNode(const RefPtr<NG::UINode>& uiNode, InspectorTreeMap& recNodes)
900 {
901     CHECK_NULL_RETURN(uiNode, nullptr);
902     RefPtr<RecNode> recNode = AceType::MakeRefPtr<RecNode>();
903     CHECK_NULL_RETURN(recNode, nullptr);
904     recNode->SetNodeId(uiNode->GetId());
905     std::string strTag = uiNode->GetTag();
906     ConvertIllegalStr(strTag);
907     recNode->SetName(strTag);
908     std::string strDebugLine = uiNode->GetDebugLine();
909     ConvertIllegalStr(strDebugLine);
910     recNode->SetDebugLine(strDebugLine);
911     auto frameNode = AceType::DynamicCast<FrameNode>(uiNode);
912     CHECK_NULL_RETURN(frameNode, nullptr);
913     auto renderContext = frameNode->GetRenderContext();
914     CHECK_NULL_RETURN(renderContext, nullptr);
915     recNode->SetSelfId(renderContext->GetNodeId());
916     recNodes.emplace(uiNode->GetId(), recNode);
917     return recNode;
918 }
919 
GetInspectorTreeInfo(std::vector<RefPtr<NG::UINode>> children,int32_t pageId,InspectorTreeMap & recNodes)920 void Inspector::GetInspectorTreeInfo(
921     std::vector<RefPtr<NG::UINode>> children, int32_t pageId, InspectorTreeMap& recNodes)
922 {
923     for (auto& uiNode : children) {
924         auto addedItem = AddInspectorTreeNode(uiNode, recNodes);
925         if (addedItem == nullptr) {
926             continue;
927         }
928         GetInspectorChildrenInfo(uiNode, recNodes, pageId);
929     }
930 }
931 
GetInspectorChildrenInfo(const RefPtr<NG::UINode> & parent,InspectorTreeMap & recNodes,int32_t pageId,uint32_t depth)932 void Inspector::GetInspectorChildrenInfo(
933     const RefPtr<NG::UINode>& parent, InspectorTreeMap& recNodes, int32_t pageId, uint32_t depth)
934 {
935     // Span is a special case in Inspector since span inherits from UINode
936     if (AceType::InstanceOf<SpanNode>(parent)) {
937         return;
938     }
939     if (AceType::InstanceOf<CustomNode>(parent)) {
940         return;
941     }
942     std::vector<RefPtr<NG::UINode>> children;
943     for (const auto& item : parent->GetChildren()) {
944         GetFrameNodeChildren(item, children, pageId, false);
945     }
946     auto node = AceType::DynamicCast<FrameNode>(parent);
947     if (node != nullptr) {
948         auto overlayNode = node->GetOverlayNode();
949         if (overlayNode != nullptr) {
950             GetFrameNodeChildren(overlayNode, children, pageId, false);
951         }
952     }
953     if (depth) {
954         for (auto uiNode : children) {
955             auto addedNode = AddInspectorTreeNode(uiNode, recNodes);
956             if (addedNode == nullptr) {
957                 continue;
958             }
959             GetInspectorChildrenInfo(uiNode, recNodes, pageId, depth - 1);
960         }
961     }
962 }
963 
GetOffScreenTreeNodes(InspectorTreeMap & nodes)964 void Inspector::GetOffScreenTreeNodes(InspectorTreeMap& nodes)
965 {
966     for (const auto& item : offscreenNodes) {
967         AddInspectorTreeNode(item, nodes);
968     }
969 }
970 } // namespace OHOS::Ace::NG
971