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