• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include "node_extened.h"
16 
17 
18 #include "node_model.h"
19 
20 #include "base/error/error_code.h"
21 #include "core/components_ng/base/ui_node.h"
22 
23 namespace OHOS::Ace::NodeModel {
24 
25 struct InnerCustomExtraParam  {
26     int32_t targetId;
27     void* userData;
28 };
29 
30 struct ExtraCustomData {
31     std::unordered_map<int64_t, InnerCustomExtraParam*> eventMap;
32 };
33 
NodeAddExtraData(ArkUI_NodeHandle node,ArkUI_NodeCustomEventType eventType,int32_t targetId,void * userData)34 void NodeAddExtraData(ArkUI_NodeHandle node, ArkUI_NodeCustomEventType eventType, int32_t targetId, void* userData)
35 {
36     if (!node->extraCustomData) {
37         node->extraCustomData = new ExtraCustomData();
38     }
39 
40     auto* extraCustomData = reinterpret_cast<ExtraCustomData*>(node->extraCustomData);
41     auto& eventMap = extraCustomData->eventMap;
42 
43     auto it = eventMap.find(eventType);
44     if (it != eventMap.end()) {
45         it->second->targetId = targetId;
46     } else {
47         auto eventExtraParam = new InnerCustomExtraParam({ targetId, userData });
48         eventMap.emplace(eventType, eventExtraParam);
49     }
50 }
51 
RegisterNodeCustomEvent(ArkUI_NodeHandle node,ArkUI_NodeCustomEventType eventType,int32_t targetId,void * userData)52 int32_t RegisterNodeCustomEvent(ArkUI_NodeHandle node, ArkUI_NodeCustomEventType eventType, int32_t targetId, void* userData)
53 {
54     if (!node || !CheckIsCNode(node)) {
55         return ERROR_CODE_PARAM_INVALID;
56     }
57     if (eventType <= 0) {
58         TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "Custom event is not supported %{public}d", eventType);
59         return ERROR_CODE_NATIVE_IMPL_TYPE_NOT_SUPPORTED;
60     }
61 
62     if (eventType & ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE) {
63         if (node->type == ARKUI_NODE_CUSTOM || node->type == ARKUI_NODE_CUSTOM_SPAN) {
64             NodeAddExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE, targetId, userData);
65         } else {
66             return ERROR_CODE_NATIVE_IMPL_TYPE_NOT_SUPPORTED;
67         }
68     }
69 
70     if (eventType & ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT) {
71         if (node->type == ARKUI_NODE_CUSTOM) {
72             NodeAddExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT, targetId, userData);
73         } else {
74             return ERROR_CODE_NATIVE_IMPL_TYPE_NOT_SUPPORTED;
75         }
76     }
77 
78     if (eventType & ARKUI_NODE_CUSTOM_EVENT_ON_DRAW) {
79         NodeAddExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW, targetId, userData);
80     }
81 
82     if (eventType & ARKUI_NODE_CUSTOM_EVENT_ON_FOREGROUND_DRAW) {
83         NodeAddExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_FOREGROUND_DRAW, targetId, userData);
84     }
85 
86     if (eventType & ARKUI_NODE_CUSTOM_EVENT_ON_OVERLAY_DRAW) {
87         NodeAddExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_OVERLAY_DRAW, targetId, userData);
88     }
89     const auto* impl = GetFullImpl();
90     if (node->type == ARKUI_NODE_CUSTOM_SPAN) {
91         impl->getExtendedAPI()->registerCustomSpanAsyncEvent(
92             node->uiNodeHandle, eventType, reinterpret_cast<void*>(node));
93     } else {
94         impl->getExtendedAPI()->registerCustomNodeAsyncEvent(
95             node->uiNodeHandle, eventType, reinterpret_cast<void*>(node));
96     }
97     return ERROR_CODE_NO_ERROR;
98 }
99 
NodeRemoveExtraData(ArkUI_NodeHandle node,ArkUI_NodeCustomEventType eventType)100 void NodeRemoveExtraData(ArkUI_NodeHandle node, ArkUI_NodeCustomEventType eventType)
101 {
102     auto* extraCustomData = reinterpret_cast<ExtraCustomData*>(node->extraCustomData);
103     auto& eventMap = extraCustomData->eventMap;
104     auto innerEventExtraParam = eventMap.find(eventType);
105     if (innerEventExtraParam == eventMap.end()) {
106         return;
107     }
108     delete innerEventExtraParam->second;
109     eventMap.erase(innerEventExtraParam);
110     if (eventMap.empty()) {
111         delete extraCustomData;
112         node->extraCustomData = nullptr;
113     }
114 }
115 
UnregisterNodeCustomEvent(ArkUI_NodeHandle node,ArkUI_NodeCustomEventType eventType)116 void UnregisterNodeCustomEvent(ArkUI_NodeHandle node, ArkUI_NodeCustomEventType eventType)
117 {
118     if (node == nullptr || !node->extraCustomData || !CheckIsCNode(node)) {
119         return;
120     }
121     const auto* impl = GetFullImpl();
122 
123     auto resultValue = impl->getExtendedAPI()->unregisterCustomNodeAsyncEvent(node->uiNodeHandle, eventType);
124     if (resultValue == -1) {
125         TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "Custom event Unregister error %{public}d", eventType);
126         return;
127     }
128 
129     if (eventType & ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE) {
130         NodeRemoveExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE);
131     }
132 
133     if (eventType & ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT) {
134         NodeRemoveExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT);
135     }
136 
137     if (eventType & ARKUI_NODE_CUSTOM_EVENT_ON_DRAW) {
138         NodeRemoveExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW);
139     }
140 
141     if (eventType & ARKUI_NODE_CUSTOM_EVENT_ON_FOREGROUND_DRAW) {
142         NodeRemoveExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_FOREGROUND_DRAW);
143     }
144 
145     if (eventType & ARKUI_NODE_CUSTOM_EVENT_ON_OVERLAY_DRAW) {
146         NodeRemoveExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_OVERLAY_DRAW);
147     }
148 }
149 
150 void (*g_customEventReceiver)(ArkUI_NodeCustomEvent* event) = nullptr;
RegisterNodeCustomReceiver(void (* eventReceiver)(ArkUI_NodeCustomEvent * event))151 void RegisterNodeCustomReceiver(void (*eventReceiver)(ArkUI_NodeCustomEvent* event))
152 {
153     g_customEventReceiver = eventReceiver;
154 }
155 
UnregisterNodeCustomEventReceiver()156 void UnregisterNodeCustomEventReceiver()
157 {
158     g_customEventReceiver = nullptr;
159 }
160 
HandleInnerCustomEvent(ArkUICustomNodeEvent * origin)161 void HandleInnerCustomEvent(ArkUICustomNodeEvent* origin)
162 {
163     if (!origin) {
164         return;
165     }
166     auto* nodePtr = reinterpret_cast<ArkUI_NodeHandle>(origin->extraParam);
167     if (!IsValidArkUINode(nodePtr) || !nodePtr->extraCustomData) {
168         return;
169     }
170 
171     auto* extraCustomData = reinterpret_cast<ExtraCustomData*>(nodePtr->extraCustomData);
172     ArkUI_NodeCustomEventType eventType = static_cast<ArkUI_NodeCustomEventType>(origin->kind);
173 
174     auto innerEventExtraParam = extraCustomData->eventMap.find(eventType);
175     if (innerEventExtraParam == extraCustomData->eventMap.end()) {
176         return;
177     }
178     ArkUI_NodeCustomEvent event;
179     event.event = origin;
180     event.node = nodePtr;
181     event.targetId = innerEventExtraParam->second->targetId;
182     event.userData = innerEventExtraParam->second->userData;
183     HandleCustomEvent(&event);
184 }
185 
HandleCustomEvent(ArkUI_NodeCustomEvent * event)186 void HandleCustomEvent(ArkUI_NodeCustomEvent* event)
187 {
188     if (!event) {
189         return;
190     }
191     if (event->node && event->node->customEventListeners) {
192         auto eventListenersSet = reinterpret_cast<std::set<void (*)(ArkUI_NodeCustomEvent*)>*>(
193             event->node->customEventListeners);
194         if (eventListenersSet) {
195             for (const auto& eventlistener : *eventListenersSet) {
196                 (*eventlistener)(event);
197             }
198         }
199     }
200     if (g_customEventReceiver) {
201         g_customEventReceiver(event);
202     }
203 }
204 
AddNodeCustomEventReceiver(ArkUI_NodeHandle nodePtr,void (* eventReceiver)(ArkUI_NodeCustomEvent * event))205 int32_t AddNodeCustomEventReceiver(ArkUI_NodeHandle nodePtr, void (*eventReceiver)(ArkUI_NodeCustomEvent* event))
206 {
207     if (!nodePtr || !eventReceiver || !CheckIsCNode(nodePtr)) {
208         return ERROR_CODE_PARAM_INVALID;
209     }
210     if (!nodePtr->customEventListeners) {
211         nodePtr->customEventListeners = new std::set<void (*)(ArkUI_NodeCustomEvent*)>();
212     }
213     auto eventListenersSet = reinterpret_cast<std::set<void (*)(ArkUI_NodeCustomEvent*)>*>(
214         nodePtr->customEventListeners);
215     if (!eventListenersSet) {
216         return ERROR_CODE_PARAM_INVALID;
217     }
218     eventListenersSet->emplace(eventReceiver);
219     return ERROR_CODE_NO_ERROR;
220 }
221 
RemoveNodeCustomEventReceiver(ArkUI_NodeHandle nodePtr,void (* eventReceiver)(ArkUI_NodeCustomEvent * event))222 int32_t RemoveNodeCustomEventReceiver(ArkUI_NodeHandle nodePtr,
223     void (*eventReceiver)(ArkUI_NodeCustomEvent* event))
224 {
225     if (!nodePtr || !eventReceiver || !nodePtr->customEventListeners || !CheckIsCNode(nodePtr)) {
226         return ERROR_CODE_PARAM_INVALID;
227     }
228     auto eventListenersSet = reinterpret_cast<std::set<void (*)(ArkUI_NodeCustomEvent*)>*>(
229         nodePtr->customEventListeners);
230     if (!eventListenersSet) {
231         return ERROR_CODE_PARAM_INVALID;
232     }
233     eventListenersSet->erase(eventReceiver);
234     if (eventListenersSet->empty()) {
235         delete eventListenersSet;
236         nodePtr->customEventListeners = nullptr;
237     }
238     return ERROR_CODE_NO_ERROR;
239 }
240 
SetMeasuredSize(ArkUI_NodeHandle node,int32_t width,int32_t height)241 int32_t SetMeasuredSize(ArkUI_NodeHandle node, int32_t width, int32_t height)
242 {
243     if (node == nullptr || !CheckIsCNode(node)) {
244         return ERROR_CODE_PARAM_INVALID;
245     }
246     const auto* impl = GetFullImpl();
247     impl->getExtendedAPI()->setMeasureWidth(node->uiNodeHandle, width > 0 ? width : 0);
248     impl->getExtendedAPI()->setMeasureHeight(node->uiNodeHandle, height > 0 ? height : 0);
249     return ERROR_CODE_NO_ERROR;
250 }
251 
SetLayoutPosition(ArkUI_NodeHandle node,int32_t positionX,int32_t positionY)252 int32_t SetLayoutPosition(ArkUI_NodeHandle node, int32_t positionX, int32_t positionY)
253 {
254     if (node == nullptr || !CheckIsCNode(node)) {
255         return ERROR_CODE_PARAM_INVALID;
256     }
257     const auto* impl = GetFullImpl();
258     impl->getExtendedAPI()->setX(node->uiNodeHandle, positionX);
259     impl->getExtendedAPI()->setY(node->uiNodeHandle, positionY);
260     return ERROR_CODE_NO_ERROR;
261 }
262 
GetLayoutConstraint(ArkUI_NodeHandle node,ArkUI_LayoutConstraint * layoutConstraint)263 int32_t GetLayoutConstraint(ArkUI_NodeHandle node, ArkUI_LayoutConstraint* layoutConstraint)
264 {
265     if (node == nullptr || layoutConstraint == nullptr || !CheckIsCNode(node)) {
266         return ERROR_CODE_PARAM_INVALID;
267     }
268     const auto* impl = GetFullImpl();
269     // data size
270     ArkUI_Int32 data[6];
271     impl->getExtendedAPI()->getLayoutConstraint(node->uiNodeHandle, data);
272     //minWidth
273     layoutConstraint->minWidth = data[0];
274     //minHeight
275     layoutConstraint->minHeight = data[1];
276     //maxWidth
277     layoutConstraint->maxWidth = data[2];
278     //maxHeight
279     layoutConstraint->maxHeight = data[3];
280     //percentReferWidth
281     layoutConstraint->percentReferWidth = data[4];
282     //percentReferHeight
283     layoutConstraint->percentReferHeight = data[5];
284     return ERROR_CODE_NO_ERROR;
285 }
286 
GetMeasuredSize(ArkUI_NodeHandle node)287 ArkUI_IntSize GetMeasuredSize(ArkUI_NodeHandle node)
288 {
289     ArkUI_IntSize size;
290     if (node == nullptr) {
291         return size;
292     }
293     const auto* impl = GetFullImpl();
294     size.width = impl->getExtendedAPI()->getMeasureWidth(node->uiNodeHandle);
295     size.height = impl->getExtendedAPI()->getMeasureHeight(node->uiNodeHandle);
296     return size;
297 }
298 
GetLayoutPosition(ArkUI_NodeHandle node)299 ArkUI_IntOffset GetLayoutPosition(ArkUI_NodeHandle node)
300 {
301     ArkUI_IntOffset offset;
302     if (node == nullptr) {
303         return offset;
304     }
305     const auto* impl = GetFullImpl();
306     offset.x = impl->getExtendedAPI()->getX(node->uiNodeHandle);
307     offset.y = impl->getExtendedAPI()->getY(node->uiNodeHandle);
308     return offset;
309 }
310 
MeasureNode(ArkUI_NodeHandle node,ArkUI_LayoutConstraint * constraint)311 int32_t MeasureNode(ArkUI_NodeHandle node, ArkUI_LayoutConstraint* constraint)
312 {
313     if (node == nullptr || constraint == nullptr || !CheckIsCNode(node)) {
314         return ERROR_CODE_PARAM_INVALID;
315     }
316     const auto* impl = GetFullImpl();
317     // data size
318     ArkUI_Float32 data[6];
319     //minWidth
320     data[0] = static_cast<ArkUI_Float32>(constraint->minWidth);
321     //minHeight
322     data[1] = static_cast<ArkUI_Float32>(constraint->minHeight);
323     //maxWidth
324     data[2] = static_cast<ArkUI_Float32>(constraint->maxWidth);
325     //maxHeight
326     data[3] = static_cast<ArkUI_Float32>(constraint->maxHeight);
327     //percentReferWidth
328     data[4] = static_cast<ArkUI_Float32>(constraint->percentReferWidth);
329     //percentReferHeight
330     data[5] = static_cast<ArkUI_Float32>(constraint->percentReferHeight);
331     impl->getExtendedAPI()->measureNode(nullptr, node->uiNodeHandle, data);
332     return ERROR_CODE_NO_ERROR;
333 }
334 
LayoutNode(ArkUI_NodeHandle node,int32_t positionX,int32_t positionY)335 int32_t LayoutNode(ArkUI_NodeHandle node, int32_t positionX, int32_t positionY)
336 {
337     if (node == nullptr || !CheckIsCNode(node)) {
338         return ERROR_CODE_PARAM_INVALID;
339     }
340     const auto* impl = GetFullImpl();
341     //layout data size
342     float data[2];
343     //positionX
344     data[0] = positionX;
345     //positionY
346     data[1] = positionY;
347     impl->getExtendedAPI()->layoutNode(nullptr, node->uiNodeHandle, &data);
348     return ERROR_CODE_NO_ERROR;
349 }
350 
GetTotalChildCount(ArkUI_NodeHandle node)351 uint32_t GetTotalChildCount(ArkUI_NodeHandle node)
352 {
353     if (node == nullptr) {
354         return 0;
355     }
356     const auto* impl = GetFullImpl();
357     return impl->getNodeModifiers()->getFrameNodeModifier()->getChildrenCount(node->uiNodeHandle, true);
358 }
359 
GetChildAt(ArkUI_NodeHandle node,int32_t position)360 ArkUI_NodeHandle GetChildAt(ArkUI_NodeHandle node, int32_t position)
361 {
362     if (node == nullptr) {
363         return nullptr;
364     }
365     const auto* impl = GetFullImpl();
366     auto* attachNode = impl->getNodeModifiers()->getFrameNodeModifier()->getChild(node->uiNodeHandle, position, true);
367     return GetArkUINode(attachNode);
368 }
369 
GetFirstChild(ArkUI_NodeHandle node)370 ArkUI_NodeHandle GetFirstChild(ArkUI_NodeHandle node)
371 {
372     if (node == nullptr) {
373         return nullptr;
374     }
375     const auto* impl = GetFullImpl();
376     auto* attachNode = impl->getNodeModifiers()->getFrameNodeModifier()->getFirst(node->uiNodeHandle, true);
377     return GetArkUINode(attachNode);
378 }
379 
GetLastChild(ArkUI_NodeHandle node)380 ArkUI_NodeHandle GetLastChild(ArkUI_NodeHandle node)
381 {
382     if (node == nullptr) {
383         return nullptr;
384     }
385     const auto* impl = GetFullImpl();
386     auto* attachNode = impl->getNodeModifiers()->getFrameNodeModifier()->getLast(node->uiNodeHandle, true);
387     return GetArkUINode(attachNode);
388 }
389 
GetPreviousSibling(ArkUI_NodeHandle node)390 ArkUI_NodeHandle GetPreviousSibling(ArkUI_NodeHandle node)
391 {
392     if (node == nullptr) {
393         return nullptr;
394     }
395     const auto* impl = GetFullImpl();
396     auto* attachNode = impl->getNodeModifiers()->getFrameNodeModifier()->getPreviousSibling(node->uiNodeHandle, true);
397     return GetArkUINode(attachNode);
398 }
399 
GetNextSibling(ArkUI_NodeHandle node)400 ArkUI_NodeHandle GetNextSibling(ArkUI_NodeHandle node)
401 {
402     if (node == nullptr) {
403         return nullptr;
404     }
405     const auto* impl = GetFullImpl();
406     auto* attachNode = impl->getNodeModifiers()->getFrameNodeModifier()->getNextSibling(node->uiNodeHandle, true);
407     return GetArkUINode(attachNode);
408 }
409 
GetParent(ArkUI_NodeHandle node)410 ArkUI_NodeHandle GetParent(ArkUI_NodeHandle node)
411 {
412     if (node == nullptr) {
413         return nullptr;
414     }
415     const auto* impl = GetFullImpl();
416     auto* value = impl->getNodeModifiers()->getFrameNodeModifier()->getParent(node->uiNodeHandle);
417     void* attachNode = impl->getExtendedAPI()->getAttachNodePtr(value);
418     if (attachNode) {
419         return reinterpret_cast<ArkUI_NodeHandle>(attachNode);
420     }
421     return nullptr;
422 }
423 
RemoveAllChildren(ArkUI_NodeHandle parentNode)424 int32_t RemoveAllChildren(ArkUI_NodeHandle parentNode)
425 {
426     CHECK_NULL_RETURN(parentNode, ERROR_CODE_PARAM_INVALID);
427     const auto* impl = GetFullImpl();
428     impl->getNodeModifiers()->getFrameNodeModifier()->clearChildren(parentNode->uiNodeHandle);
429     return ERROR_CODE_NO_ERROR;
430 }
431 } // namespace OHOS::Ace::NodeModel
432