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