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