• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/base/inspector.h"
17 
18 #include <unordered_set>
19 
20 #include "base/memory/ace_type.h"
21 #include "base/utils/utils.h"
22 #include "core/common/ace_application_info.h"
23 #include "core/common/container.h"
24 #include "core/common/recorder/event_recorder.h"
25 #include "core/components_ng/base/ui_node.h"
26 #include "core/components_ng/pattern/stage/page_info.h"
27 #include "core/components_ng/pattern/stage/page_pattern.h"
28 #include "core/components_ng/pattern/text/span_node.h"
29 #include "core/components_v2/inspector/inspector_constants.h"
30 #include "core/pipeline_ng/pipeline_context.h"
31 #include "frameworks/base/memory/type_info_base.h"
32 
33 namespace OHOS::Ace::NG {
34 namespace {
35 const char INSPECTOR_TYPE[] = "$type";
36 const char INSPECTOR_ID[] = "$ID";
37 const char INSPECTOR_RECT[] = "$rect";
38 const char INSPECTOR_ATTRS[] = "$attrs";
39 const char INSPECTOR_ROOT[] = "root";
40 const char INSPECTOR_PAGE_URL[] = "pageUrl";
41 const char INSPECTOR_NAV_DST_NAME[] = "navDstName";
42 const char INSPECTOR_WIDTH[] = "width";
43 const char INSPECTOR_HEIGHT[] = "height";
44 const char INSPECTOR_RESOLUTION[] = "$resolution";
45 const char INSPECTOR_CHILDREN[] = "$children";
46 const char INSPECTOR_DEBUGLINE[] = "$debugLine";
47 #ifdef PREVIEW
48 const char INSPECTOR_VIEW_ID[] = "$viewID";
49 #endif
50 const char INSPECTOR_ATTR_ID[] = "id";
51 const char INSPECTOR_LABEL[] = "label";
52 const char INSPECTOR_CONTENT[] = "content";
53 const char INSPECTOR_ENABLED[] = "enabled";
54 const char INSPECTOR_OPACITY[] = "opacity";
55 const char INSPECTOR_ZINDEX[] = "zindex";
56 const char INSPECTOR_VISIBILITY[] = "visibility";
57 
58 const uint32_t LONG_PRESS_DELAY = 1000;
59 RectF deviceRect;
60 
GetInspectorByKey(const RefPtr<FrameNode> & root,const std::string & key)61 RefPtr<UINode> GetInspectorByKey(const RefPtr<FrameNode>& root, const std::string& key)
62 {
63     std::queue<RefPtr<UINode>> elements;
64     elements.push(root);
65     RefPtr<UINode> inspectorElement;
66     while (!elements.empty()) {
67         auto current = elements.front();
68         elements.pop();
69         if (key == current->GetInspectorId().value_or("")) {
70             return current;
71         }
72 
73         const auto& children = current->GetChildren();
74         for (const auto& child : children) {
75             elements.push(child);
76         }
77     }
78     return nullptr;
79 }
80 
DumpElementTree(int32_t depth,const RefPtr<UINode> & element,std::map<int32_t,std::list<RefPtr<UINode>>> & depthElementMap)81 void DumpElementTree(
82     int32_t depth, const RefPtr<UINode>& element, std::map<int32_t, std::list<RefPtr<UINode>>>& depthElementMap)
83 {
84     if (element->GetChildren().empty()) {
85         return;
86     }
87     const auto& children = element->GetChildren();
88     depthElementMap[depth].insert(depthElementMap[depth].end(), children.begin(), children.end());
89     for (const auto& depthElement : children) {
90         DumpElementTree(depth + 1, depthElement, depthElementMap);
91     }
92 }
93 
GetUpPoint(const TouchEvent & downPoint)94 TouchEvent GetUpPoint(const TouchEvent& downPoint)
95 {
96     return { .x = downPoint.x,
97         .y = downPoint.y,
98         .type = TouchType::UP,
99         .time = std::chrono::high_resolution_clock::now(),
100         .sourceType = SourceType::TOUCH };
101 }
102 #ifdef PREVIEW
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::vector<RefPtr<NG::UINode>> & children,int32_t pageId)103 void GetFrameNodeChildren(const RefPtr<NG::UINode>& uiNode, std::vector<RefPtr<NG::UINode>>& children, int32_t pageId)
104 {
105     // Set ViewId for the fast preview.
106     auto parent = uiNode->GetParent();
107     if (parent && parent->GetTag() == "JsView") {
108         uiNode->SetViewId(std::to_string(parent->GetId()));
109     } else {
110         uiNode->SetViewId(parent->GetViewId());
111     }
112     if (uiNode->GetTag() == "stage") {
113     } else if (uiNode->GetTag() == "page") {
114         if (uiNode->GetPageId() != pageId) {
115             return;
116         }
117     } else {
118         if (!uiNode->GetDebugLine().empty()) {
119             children.emplace_back(uiNode);
120             return;
121         }
122     }
123 
124     for (const auto& frameChild : uiNode->GetChildren()) {
125         GetFrameNodeChildren(frameChild, children, pageId);
126     }
127 }
128 
GetSpanInspector(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId)129 void GetSpanInspector(
130     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId)
131 {
132     // span rect follows parent text size
133     auto spanParentNode = parent->GetParent();
134     while (spanParentNode != nullptr) {
135         if (AceType::InstanceOf<NG::FrameNode>(spanParentNode)) {
136             break;
137         }
138         spanParentNode = spanParentNode->GetParent();
139     }
140     CHECK_NULL_VOID(spanParentNode);
141     auto node = AceType::DynamicCast<FrameNode>(spanParentNode);
142     auto jsonNode = JsonUtil::Create(true);
143     auto jsonObject = JsonUtil::Create(true);
144     parent->ToJsonValue(jsonObject);
145     jsonNode->Put(INSPECTOR_ATTRS, jsonObject);
146     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
147     jsonNode->Put(INSPECTOR_ID, parent->GetId());
148     RectF rect = node->GetTransformRectRelativeToWindow();
149     rect = rect.Constrain(deviceRect);
150     if (rect.IsEmpty()) {
151         rect.SetRect(0, 0, 0, 0);
152     }
153     auto strRec = std::to_string(rect.Left())
154                       .append(",")
155                       .append(std::to_string(rect.Top()))
156                       .append(",")
157                       .append(std::to_string(rect.Width()))
158                       .append(",")
159                       .append(std::to_string(rect.Height()));
160     jsonNode->Put(INSPECTOR_RECT, strRec.c_str());
161     jsonNode->Put(INSPECTOR_DEBUGLINE, parent->GetDebugLine().c_str());
162     jsonNode->Put(INSPECTOR_VIEW_ID, parent->GetViewId().c_str());
163     jsonNodeArray->Put(jsonNode);
164 }
165 
GetInspectorChildren(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId,bool isActive)166 void GetInspectorChildren(
167     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId, bool isActive)
168 {
169     // Span is a special case in Inspector since span inherits from UINode
170     if (AceType::InstanceOf<SpanNode>(parent)) {
171         GetSpanInspector(parent, jsonNodeArray, pageId);
172         return;
173     }
174     auto jsonNode = JsonUtil::Create(true);
175     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
176     jsonNode->Put(INSPECTOR_ID, parent->GetId());
177     auto node = AceType::DynamicCast<FrameNode>(parent);
178     if (node) {
179         RectF rect;
180         isActive = isActive && node->IsActive();
181         if (isActive) {
182             rect = node->GetTransformRectRelativeToWindow();
183         }
184         rect = rect.Constrain(deviceRect);
185         if (rect.IsEmpty()) {
186             rect.SetRect(0, 0, 0, 0);
187         }
188         auto strRec = std::to_string(rect.Left())
189                           .append(",")
190                           .append(std::to_string(rect.Top()))
191                           .append(",")
192                           .append(std::to_string(rect.Width()))
193                           .append(",")
194                           .append(std::to_string(rect.Height()));
195         jsonNode->Put(INSPECTOR_RECT, strRec.c_str());
196         jsonNode->Put(INSPECTOR_DEBUGLINE, node->GetDebugLine().c_str());
197         jsonNode->Put(INSPECTOR_VIEW_ID, node->GetViewId().c_str());
198         auto jsonObject = JsonUtil::Create(true);
199         parent->ToJsonValue(jsonObject);
200         jsonNode->Put(INSPECTOR_ATTRS, jsonObject);
201     }
202 
203     std::vector<RefPtr<NG::UINode>> children;
204     for (const auto& item : parent->GetChildren()) {
205         GetFrameNodeChildren(item, children, pageId);
206     }
207     auto jsonChildrenArray = JsonUtil::CreateArray(true);
208     for (auto uiNode : children) {
209         GetInspectorChildren(uiNode, jsonChildrenArray, pageId, isActive);
210     }
211     if (jsonChildrenArray->GetArraySize()) {
212         jsonNode->Put(INSPECTOR_CHILDREN, jsonChildrenArray);
213     }
214     jsonNodeArray->Put(jsonNode);
215 }
216 
217 #else
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::vector<RefPtr<NG::UINode>> & children,int32_t pageId)218 void GetFrameNodeChildren(const RefPtr<NG::UINode>& uiNode, std::vector<RefPtr<NG::UINode>>& children, int32_t pageId)
219 {
220     if (AceType::InstanceOf<NG::FrameNode>(uiNode) || AceType::InstanceOf<SpanNode>(uiNode)) {
221         if (uiNode->GetTag() == "stage") {
222         } else if (uiNode->GetTag() == "page") {
223             if (uiNode->GetPageId() != pageId) {
224                 return;
225             }
226         } else {
227             auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
228             auto spanNode = AceType::DynamicCast<NG::SpanNode>(uiNode);
229             if ((frameNode && !frameNode->IsInternal()) || spanNode) {
230                 children.emplace_back(uiNode);
231                 return;
232             }
233         }
234     }
235 
236     for (const auto& frameChild : uiNode->GetChildren()) {
237         GetFrameNodeChildren(frameChild, children, pageId);
238     }
239 }
240 
GetSpanInspector(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId)241 void GetSpanInspector(
242     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId)
243 {
244     // span rect follows parent text size
245     auto spanParentNode = parent->GetParent();
246     while (spanParentNode != nullptr) {
247         if (AceType::InstanceOf<NG::FrameNode>(spanParentNode)) {
248             break;
249         }
250         spanParentNode = spanParentNode->GetParent();
251     }
252     CHECK_NULL_VOID(spanParentNode);
253     auto node = AceType::DynamicCast<FrameNode>(spanParentNode);
254     auto jsonNode = JsonUtil::Create(true);
255     auto jsonObject = JsonUtil::Create(true);
256     parent->ToJsonValue(jsonObject);
257     jsonNode->Put(INSPECTOR_ATTRS, jsonObject);
258     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
259     jsonNode->Put(INSPECTOR_ID, parent->GetId());
260     jsonNode->Put(INSPECTOR_DEBUGLINE, parent->GetDebugLine().c_str());
261     RectF rect = node->GetTransformRectRelativeToWindow();
262     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
263     jsonNodeArray->Put(jsonNode);
264 }
265 
GetInspectorChildren(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId,bool isActive)266 void GetInspectorChildren(
267     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId, bool isActive)
268 {
269     // Span is a special case in Inspector since span inherits from UINode
270     if (AceType::InstanceOf<SpanNode>(parent)) {
271         GetSpanInspector(parent, jsonNodeArray, pageId);
272         return;
273     }
274     auto jsonNode = JsonUtil::Create(true);
275     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
276     jsonNode->Put(INSPECTOR_ID, parent->GetId());
277     auto node = AceType::DynamicCast<FrameNode>(parent);
278     auto ctx = node->GetRenderContext();
279 
280     RectF rect;
281     isActive = isActive && node->IsActive();
282     if (isActive) {
283         rect = node->GetTransformRectRelativeToWindow();
284     }
285 
286     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
287     jsonNode->Put(INSPECTOR_DEBUGLINE, node->GetDebugLine().c_str());
288     auto jsonObject = JsonUtil::Create(true);
289     parent->ToJsonValue(jsonObject);
290     jsonNode->Put(INSPECTOR_ATTRS, jsonObject);
291     std::vector<RefPtr<NG::UINode>> children;
292     for (const auto& item : parent->GetChildren()) {
293         GetFrameNodeChildren(item, children, pageId);
294     }
295     auto jsonChildrenArray = JsonUtil::CreateArray(true);
296     for (auto uiNode : children) {
297         GetInspectorChildren(uiNode, jsonChildrenArray, pageId, isActive);
298     }
299     if (jsonChildrenArray->GetArraySize()) {
300         jsonNode->Put(INSPECTOR_CHILDREN, jsonChildrenArray);
301     }
302     jsonNodeArray->Put(jsonNode);
303 }
304 #endif
305 
GetOverlayNode(const RefPtr<NG::UINode> & pageNode)306 RefPtr<NG::UINode> GetOverlayNode(const RefPtr<NG::UINode>& pageNode)
307 {
308     CHECK_NULL_RETURN(pageNode, nullptr);
309     auto stageNode = pageNode->GetParent();
310     CHECK_NULL_RETURN(stageNode, nullptr);
311     auto stageParent = stageNode->GetParent();
312     CHECK_NULL_RETURN(stageParent, nullptr);
313     auto overlayNode = stageParent->GetChildren().back();
314     if (overlayNode->GetTag() == "stage") {
315         return nullptr;
316     }
317     return overlayNode;
318 }
319 
GetContextInfo(const RefPtr<PipelineContext> & context,std::unique_ptr<JsonValue> & jsonRoot)320 void GetContextInfo(const RefPtr<PipelineContext>& context, std::unique_ptr<JsonValue>& jsonRoot)
321 {
322     auto scale = context->GetViewScale();
323     auto rootHeight = context->GetRootHeight();
324     auto rootWidth = context->GetRootWidth();
325     deviceRect.SetRect(0, 0, rootWidth * scale, rootHeight * scale);
326     jsonRoot->Put(INSPECTOR_WIDTH, std::to_string(rootWidth * scale).c_str());
327     jsonRoot->Put(INSPECTOR_HEIGHT, std::to_string(rootHeight * scale).c_str());
328     jsonRoot->Put(INSPECTOR_RESOLUTION, std::to_string(PipelineBase::GetCurrentDensity()).c_str());
329 }
330 
GetInspectorInfo(std::vector<RefPtr<NG::UINode>> children,int32_t pageId,std::unique_ptr<JsonValue> jsonRoot,bool isLayoutInspector)331 std::string GetInspectorInfo(std::vector<RefPtr<NG::UINode>> children, int32_t pageId,
332     std::unique_ptr<JsonValue> jsonRoot, bool isLayoutInspector)
333 {
334     auto jsonNodeArray = JsonUtil::CreateArray(true);
335     for (auto& uiNode : children) {
336         GetInspectorChildren(uiNode, jsonNodeArray, pageId, true);
337     }
338     if (jsonNodeArray->GetArraySize()) {
339         jsonRoot->Put(INSPECTOR_CHILDREN, jsonNodeArray);
340     }
341 
342     if (isLayoutInspector) {
343         auto jsonTree = JsonUtil::Create(true);
344         jsonTree->Put("type", "root");
345         jsonTree->Put("content", jsonRoot);
346         return jsonTree->ToString();
347     }
348 
349     return jsonRoot->ToString();
350 }
351 } // namespace
352 
353 std::set<RefPtr<FrameNode>> Inspector::offscreenNodes;
354 
GetFrameNodeByKey(const std::string & key)355 RefPtr<FrameNode> Inspector::GetFrameNodeByKey(const std::string& key)
356 {
357     if (!offscreenNodes.empty()) {
358         for (auto node : offscreenNodes) {
359             auto frameNode = AceType::DynamicCast<FrameNode>(GetInspectorByKey(node, key));
360             if (frameNode) {
361                 return frameNode;
362             }
363         }
364     }
365     auto context = NG::PipelineContext::GetCurrentContext();
366     CHECK_NULL_RETURN(context, nullptr);
367     auto rootNode = context->GetRootElement();
368     CHECK_NULL_RETURN(rootNode, nullptr);
369 
370     return AceType::DynamicCast<FrameNode>(GetInspectorByKey(rootNode, key));
371 }
372 
GetInspectorNodeByKey(const std::string & key)373 std::string Inspector::GetInspectorNodeByKey(const std::string& key)
374 {
375     auto context = NG::PipelineContext::GetCurrentContext();
376     CHECK_NULL_RETURN(context, "");
377     auto rootNode = context->GetRootElement();
378     CHECK_NULL_RETURN(rootNode, "");
379 
380     auto inspectorElement = GetInspectorByKey(rootNode, key);
381     CHECK_NULL_RETURN(inspectorElement, "");
382 
383     auto jsonNode = JsonUtil::Create(true);
384     jsonNode->Put(INSPECTOR_TYPE, inspectorElement->GetTag().c_str());
385     jsonNode->Put(INSPECTOR_ID, inspectorElement->GetId());
386     auto frameNode = AceType::DynamicCast<FrameNode>(inspectorElement);
387     if (frameNode) {
388         auto rect = frameNode->GetTransformRectRelativeToWindow();
389         jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
390     }
391     auto jsonAttrs = JsonUtil::Create(true);
392     std::string debugLine = inspectorElement->GetDebugLine();
393     jsonNode->Put(INSPECTOR_DEBUGLINE, debugLine.c_str());
394     inspectorElement->ToJsonValue(jsonAttrs);
395     jsonNode->Put(INSPECTOR_ATTRS, jsonAttrs);
396     return jsonNode->ToString();
397 }
398 
GetRectangleById(const std::string & key,Rectangle & rectangle)399 void Inspector::GetRectangleById(const std::string& key, Rectangle& rectangle)
400 {
401     auto frameNode = Inspector::GetFrameNodeByKey(key);
402     CHECK_NULL_VOID(frameNode);
403     rectangle.size = frameNode->GetGeometryNode()->GetFrameSize();
404     auto context = frameNode->GetRenderContext();
405     CHECK_NULL_VOID(context);
406     rectangle.localOffset = context->GetPaintRectWithTransform().GetOffset();
407     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
408         rectangle.windowOffset = frameNode->GetTransformRelativeOffset();
409     } else {
410         rectangle.windowOffset = frameNode->GetOffsetRelativeToWindow();
411     }
412     auto pipeline = NG::PipelineContext::GetCurrentContext();
413     CHECK_NULL_VOID(pipeline);
414     rectangle.screenRect = pipeline->GetCurrentWindowRect();
415     auto renderContext = frameNode->GetRenderContext();
416     CHECK_NULL_VOID(renderContext);
417     Matrix4 defMatrix4 = Matrix4::CreateIdentity();
418     Matrix4 matrix4 = renderContext->GetTransformMatrixValue(defMatrix4);
419     rectangle.matrix4 = matrix4;
420     auto rect = renderContext->GetPaintRectWithoutTransform();
421     const double halfDimension = 50.0;
422     auto center = renderContext->GetTransformCenter().value_or(DimensionOffset(
423         Dimension(halfDimension, DimensionUnit::PERCENT), Dimension(halfDimension, DimensionUnit::PERCENT)));
424     double centerX = 0.0;
425     double centerY = 0.0;
426     if (center.GetX().Unit() == DimensionUnit::PERCENT || center.GetY().Unit() == DimensionUnit::PERCENT) {
427         if (rect.IsValid()) {
428             centerX = Dimension(center.GetX().ConvertToPxWithSize(rect.Width()), DimensionUnit::PX).ConvertToVp();
429             centerY = Dimension(center.GetY().ConvertToPxWithSize(rect.Height()), DimensionUnit::PX).ConvertToVp();
430         }
431     } else {
432         centerX = center.GetX().ConvertToVp();
433         centerY = center.GetY().ConvertToVp();
434     }
435     VectorF defScale = VectorF(1.0, 1.0);
436     VectorF scale = renderContext->GetTransformScaleValue(defScale);
437     rectangle.scale.x = scale.x;
438     rectangle.scale.y = scale.y;
439     rectangle.scale.z = 1.0;
440     rectangle.scale.centerX = centerX;
441     rectangle.scale.centerY = centerY;
442     Vector5F defRotate = Vector5F(0.0, 0.0, 0.0, 0.0, 0.0);
443     Vector5F rotate = renderContext->GetTransformRotateValue(defRotate);
444     rectangle.rotate.x = rotate.x;
445     rectangle.rotate.y = rotate.y;
446     rectangle.rotate.z = rotate.z;
447     rectangle.rotate.angle = rotate.w;
448     rectangle.rotate.centerX = centerX;
449     rectangle.rotate.centerY = centerY;
450     TranslateOptions defTranslate = TranslateOptions(0.0, 0.0, 0.0);
451     TranslateOptions translate = renderContext->GetTransformTranslateValue(defTranslate);
452     if ((translate.x.Unit() == DimensionUnit::PERCENT) && rect.IsValid()) {
453         rectangle.translate.x =
454             Dimension(translate.x.ConvertToPxWithSize(rect.Width()), DimensionUnit::PX).ConvertToVp();
455     } else {
456         rectangle.translate.x = translate.x.ConvertToVp();
457     }
458     if ((translate.y.Unit() == DimensionUnit::PERCENT) && rect.IsValid()) {
459         rectangle.translate.y =
460             Dimension(translate.y.ConvertToPxWithSize(rect.Height()), DimensionUnit::PX).ConvertToVp();
461     } else {
462         rectangle.translate.y = translate.y.ConvertToVp();
463     }
464     rectangle.translate.z = translate.z.ConvertToVp();
465 }
GetInspector(bool isLayoutInspector)466 std::string Inspector::GetInspector(bool isLayoutInspector)
467 {
468     auto jsonRoot = JsonUtil::Create(true);
469     jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
470 
471     auto context = NG::PipelineContext::GetCurrentContext();
472     CHECK_NULL_RETURN(context, jsonRoot->ToString());
473     GetContextInfo(context, jsonRoot);
474     auto pageRootNode = context->GetStageManager()->GetLastPage();
475     CHECK_NULL_RETURN(pageRootNode, jsonRoot->ToString());
476     auto pageId = context->GetStageManager()->GetLastPage()->GetPageId();
477     std::vector<RefPtr<NG::UINode>> children;
478     for (const auto& item : pageRootNode->GetChildren()) {
479         GetFrameNodeChildren(item, children, pageId);
480     }
481     auto overlayNode = GetOverlayNode(pageRootNode);
482     if (overlayNode) {
483         GetFrameNodeChildren(overlayNode, children, pageId);
484     }
485 
486     return GetInspectorInfo(children, pageId, std::move(jsonRoot), isLayoutInspector);
487 }
488 
GetSubWindowInspector(bool isLayoutInspector)489 std::string Inspector::GetSubWindowInspector(bool isLayoutInspector)
490 {
491     auto jsonRoot = JsonUtil::Create(true);
492     jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
493 
494     auto context = NG::PipelineContext::GetCurrentContext();
495     CHECK_NULL_RETURN(context, jsonRoot->ToString());
496     GetContextInfo(context, jsonRoot);
497     auto overlayNode = context->GetOverlayManager()->GetRootNode().Upgrade();
498     CHECK_NULL_RETURN(overlayNode, jsonRoot->ToString());
499     auto pageId = 0;
500     std::vector<RefPtr<NG::UINode>> children;
501     GetFrameNodeChildren(overlayNode, children, pageId);
502 
503     return GetInspectorInfo(children, 0, std::move(jsonRoot), isLayoutInspector);
504 }
505 
FillSimplifiedInspectorAttrs(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNode)506 void FillSimplifiedInspectorAttrs(const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNode)
507 {
508     auto tmpJson = JsonUtil::Create(true);
509     parent->ToJsonValue(tmpJson);
510     jsonNode->Put(INSPECTOR_ATTR_ID, tmpJson->GetString(INSPECTOR_ATTR_ID).c_str());
511 
512     auto jsonObject = JsonUtil::Create(true);
513     if (tmpJson->Contains(INSPECTOR_LABEL)) {
514         jsonObject->Put(INSPECTOR_LABEL, tmpJson->GetString(INSPECTOR_LABEL).c_str());
515     }
516     if (tmpJson->Contains(INSPECTOR_CONTENT)) {
517         jsonObject->Put(INSPECTOR_CONTENT, tmpJson->GetString(INSPECTOR_CONTENT).c_str());
518     }
519     jsonObject->Put(INSPECTOR_ENABLED, tmpJson->GetBool(INSPECTOR_ENABLED));
520     jsonObject->Put(INSPECTOR_OPACITY, tmpJson->GetDouble(INSPECTOR_OPACITY));
521     jsonObject->Put(INSPECTOR_ZINDEX, tmpJson->GetInt(INSPECTOR_ZINDEX));
522     jsonObject->Put(INSPECTOR_VISIBILITY, tmpJson->GetString(INSPECTOR_VISIBILITY).c_str());
523     jsonNode->Put(INSPECTOR_ATTRS, jsonObject);
524 }
525 
GetSimplifiedSpanInspector(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId)526 void GetSimplifiedSpanInspector(
527     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId)
528 {
529     // span rect follows parent text size
530     auto spanParentNode = parent->GetParent();
531     CHECK_NULL_VOID(spanParentNode);
532     auto node = AceType::DynamicCast<FrameNode>(spanParentNode);
533     CHECK_NULL_VOID(node);
534     auto jsonNode = JsonUtil::Create(true);
535 
536     FillSimplifiedInspectorAttrs(parent, jsonNode);
537 
538     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
539     RectF rect = node->GetTransformRectRelativeToWindow();
540     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
541     jsonNodeArray->Put(jsonNode);
542 }
543 
GetSimplifiedInspectorChildren(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId,bool isActive)544 void GetSimplifiedInspectorChildren(
545     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId, bool isActive)
546 {
547     // Span is a special case in Inspector since span inherits from UINode
548     if (AceType::InstanceOf<SpanNode>(parent)) {
549         GetSimplifiedSpanInspector(parent, jsonNodeArray, pageId);
550         return;
551     }
552     auto jsonNode = JsonUtil::Create(true);
553     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
554     auto node = AceType::DynamicCast<FrameNode>(parent);
555     auto ctx = node->GetRenderContext();
556 
557     RectF rect;
558     isActive = isActive && node->IsActive();
559     if (isActive) {
560         rect = node->GetTransformRectRelativeToWindow();
561     }
562 
563     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
564 
565     FillSimplifiedInspectorAttrs(parent, jsonNode);
566 
567     std::vector<RefPtr<NG::UINode>> children;
568     for (const auto& item : parent->GetChildren()) {
569         GetFrameNodeChildren(item, children, pageId);
570     }
571     auto jsonChildrenArray = JsonUtil::CreateArray(true);
572     for (auto uiNode : children) {
573         GetSimplifiedInspectorChildren(uiNode, jsonChildrenArray, pageId, isActive);
574     }
575     if (jsonChildrenArray->GetArraySize()) {
576         jsonNode->Put(INSPECTOR_CHILDREN, jsonChildrenArray);
577     }
578     jsonNodeArray->Put(jsonNode);
579 }
580 
GetSimplifiedInspector(int32_t containerId)581 std::string Inspector::GetSimplifiedInspector(int32_t containerId)
582 {
583     TAG_LOGI(AceLogTag::ACE_UIEVENT, "GetSimplifiedInspector start: container %{public}d", containerId);
584     auto jsonRoot = JsonUtil::Create(true);
585     jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
586 
587     auto context = NG::PipelineContext::GetContextByContainerId(containerId);
588     CHECK_NULL_RETURN(context, jsonRoot->ToString());
589     auto scale = context->GetViewScale();
590     auto rootHeight = context->GetRootHeight();
591     auto rootWidth = context->GetRootWidth();
592     deviceRect.SetRect(0, 0, rootWidth * scale, rootHeight * scale);
593     jsonRoot->Put(INSPECTOR_WIDTH, std::to_string(rootWidth * scale).c_str());
594     jsonRoot->Put(INSPECTOR_HEIGHT, std::to_string(rootHeight * scale).c_str());
595     jsonRoot->Put(INSPECTOR_RESOLUTION, std::to_string(SystemProperties::GetResolution()).c_str());
596 
597     auto pageRootNode = context->GetStageManager()->GetLastPage();
598     CHECK_NULL_RETURN(pageRootNode, jsonRoot->ToString());
599 
600     auto pagePattern = pageRootNode->GetPattern<PagePattern>();
601     CHECK_NULL_RETURN(pagePattern, jsonRoot->ToString());
602     auto pageInfo = pagePattern->GetPageInfo();
603     CHECK_NULL_RETURN(pageInfo, jsonRoot->ToString());
604     jsonRoot->Put(INSPECTOR_PAGE_URL, pageInfo->GetPageUrl().c_str());
605     jsonRoot->Put(INSPECTOR_NAV_DST_NAME, Recorder::EventRecorder::Get().GetNavDstName().c_str());
606 
607     auto pageId = context->GetStageManager()->GetLastPage()->GetPageId();
608     std::vector<RefPtr<NG::UINode>> children;
609     for (const auto& item : pageRootNode->GetChildren()) {
610         GetFrameNodeChildren(item, children, pageId);
611     }
612     auto overlayNode = GetOverlayNode(pageRootNode);
613     if (overlayNode) {
614         GetFrameNodeChildren(overlayNode, children, pageId);
615     }
616     auto jsonNodeArray = JsonUtil::CreateArray(true);
617     for (auto& uiNode : children) {
618         GetSimplifiedInspectorChildren(uiNode, jsonNodeArray, pageId, true);
619     }
620     if (jsonNodeArray->GetArraySize()) {
621         jsonRoot->Put(INSPECTOR_CHILDREN, jsonNodeArray);
622     }
623 
624     return jsonRoot->ToString();
625 }
626 
SendEventByKey(const std::string & key,int action,const std::string & params)627 bool Inspector::SendEventByKey(const std::string& key, int action, const std::string& params)
628 {
629     auto context = NG::PipelineContext::GetCurrentContext();
630     CHECK_NULL_RETURN(context, false);
631     auto rootNode = context->GetRootElement();
632     CHECK_NULL_RETURN(rootNode, false);
633 
634     auto inspectorElement = AceType::DynamicCast<FrameNode>(GetInspectorByKey(rootNode, key));
635     CHECK_NULL_RETURN(inspectorElement, false);
636 
637     auto size = inspectorElement->GetGeometryNode()->GetFrameSize();
638     auto offset = inspectorElement->GetTransformRelativeOffset();
639     Rect rect { offset.GetX(), offset.GetY(), size.Width(), size.Height() };
640     context->GetTaskExecutor()->PostTask(
641         [weak = AceType::WeakClaim(AceType::RawPtr(context)), rect, action, params]() {
642             auto context = weak.Upgrade();
643             if (!context) {
644                 return;
645             }
646 
647             TouchEvent point { .x = (rect.Left() + rect.Width() / 2),
648                 .y = (rect.Top() + rect.Height() / 2),
649                 .type = TouchType::DOWN,
650                 .time = std::chrono::high_resolution_clock::now(),
651                 .sourceType = SourceType::TOUCH };
652             context->OnTouchEvent(point.UpdatePointers());
653 
654             switch (action) {
655                 case static_cast<int>(AceAction::ACTION_CLICK): {
656                     context->OnTouchEvent(GetUpPoint(point).UpdatePointers());
657                     break;
658                 }
659                 case static_cast<int>(AceAction::ACTION_LONG_CLICK): {
660                     CancelableCallback<void()> inspectorTimer;
661                     auto&& callback = [weak, point]() {
662                         auto refPtr = weak.Upgrade();
663                         if (refPtr) {
664                             refPtr->OnTouchEvent(GetUpPoint(point).UpdatePointers());
665                         }
666                     };
667                     inspectorTimer.Reset(callback);
668                     auto taskExecutor =
669                         SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
670                     taskExecutor.PostDelayedTask(inspectorTimer, LONG_PRESS_DELAY);
671                     break;
672                 }
673                 default:
674                     break;
675             }
676         },
677         TaskExecutor::TaskType::UI);
678 
679     return true;
680 }
681 
HideAllMenus()682 void Inspector::HideAllMenus()
683 {
684     auto context = NG::PipelineContext::GetCurrentContext();
685     CHECK_NULL_VOID(context);
686     auto overlayManager = context->GetOverlayManager();
687     CHECK_NULL_VOID(overlayManager);
688     overlayManager->HideAllMenus();
689 }
690 
AddOffscreenNode(RefPtr<FrameNode> node)691 void Inspector::AddOffscreenNode(RefPtr<FrameNode> node)
692 {
693     CHECK_NULL_VOID(node);
694     offscreenNodes.insert(node);
695 }
696 
RemoveOffscreenNode(RefPtr<FrameNode> node)697 void Inspector::RemoveOffscreenNode(RefPtr<FrameNode> node)
698 {
699     CHECK_NULL_VOID(node);
700     offscreenNodes.erase(node);
701 }
702 
703 } // namespace OHOS::Ace::NG
704