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_DRAW_FRONT) {
83 NodeAddExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW_FRONT, targetId, userData);
84 }
85
86 if (eventType & ARKUI_NODE_CUSTOM_EVENT_ON_DRAW_BEHIND) {
87 NodeAddExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW_BEHIND, 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_DRAW_FRONT) {
150 NodeRemoveExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW_FRONT);
151 }
152
153 if (eventType & ARKUI_NODE_CUSTOM_EVENT_ON_DRAW_BEHIND) {
154 NodeRemoveExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW_BEHIND);
155 }
156
157 if (eventType & ARKUI_NODE_CUSTOM_EVENT_ON_FOREGROUND_DRAW) {
158 NodeRemoveExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_FOREGROUND_DRAW);
159 }
160
161 if (eventType & ARKUI_NODE_CUSTOM_EVENT_ON_OVERLAY_DRAW) {
162 NodeRemoveExtraData(node, ARKUI_NODE_CUSTOM_EVENT_ON_OVERLAY_DRAW);
163 }
164 }
165
166 void (*g_customEventReceiver)(ArkUI_NodeCustomEvent* event) = nullptr;
RegisterNodeCustomReceiver(void (* eventReceiver)(ArkUI_NodeCustomEvent * event))167 void RegisterNodeCustomReceiver(void (*eventReceiver)(ArkUI_NodeCustomEvent* event))
168 {
169 g_customEventReceiver = eventReceiver;
170 }
171
UnregisterNodeCustomEventReceiver()172 void UnregisterNodeCustomEventReceiver()
173 {
174 g_customEventReceiver = nullptr;
175 }
176
HandleInnerCustomEvent(ArkUICustomNodeEvent * origin)177 void HandleInnerCustomEvent(ArkUICustomNodeEvent* origin)
178 {
179 if (!origin) {
180 return;
181 }
182 auto* nodePtr = reinterpret_cast<ArkUI_NodeHandle>(origin->extraParam);
183 if (!IsValidArkUINode(nodePtr) || !nodePtr->extraCustomData) {
184 return;
185 }
186
187 auto* extraCustomData = reinterpret_cast<ExtraCustomData*>(nodePtr->extraCustomData);
188 ArkUI_NodeCustomEventType eventType = static_cast<ArkUI_NodeCustomEventType>(origin->kind);
189
190 auto innerEventExtraParam = extraCustomData->eventMap.find(eventType);
191 if (innerEventExtraParam == extraCustomData->eventMap.end()) {
192 return;
193 }
194 ArkUI_NodeCustomEvent event;
195 event.event = origin;
196 event.node = nodePtr;
197 event.targetId = innerEventExtraParam->second->targetId;
198 event.userData = innerEventExtraParam->second->userData;
199 HandleCustomEvent(&event);
200 }
201
HandleCustomEvent(ArkUI_NodeCustomEvent * event)202 void HandleCustomEvent(ArkUI_NodeCustomEvent* event)
203 {
204 if (!event) {
205 return;
206 }
207 if (event->node && event->node->customEventListeners) {
208 auto eventListenersSet = reinterpret_cast<std::set<void (*)(ArkUI_NodeCustomEvent*)>*>(
209 event->node->customEventListeners);
210 if (eventListenersSet) {
211 for (const auto& eventlistener : *eventListenersSet) {
212 (*eventlistener)(event);
213 }
214 }
215 }
216 if (g_customEventReceiver) {
217 g_customEventReceiver(event);
218 }
219 }
220
AddNodeCustomEventReceiver(ArkUI_NodeHandle nodePtr,void (* eventReceiver)(ArkUI_NodeCustomEvent * event))221 int32_t AddNodeCustomEventReceiver(ArkUI_NodeHandle nodePtr, void (*eventReceiver)(ArkUI_NodeCustomEvent* event))
222 {
223 if (!nodePtr || !eventReceiver || !CheckIsCNode(nodePtr)) {
224 return ERROR_CODE_PARAM_INVALID;
225 }
226 if (!nodePtr->customEventListeners) {
227 nodePtr->customEventListeners = new std::set<void (*)(ArkUI_NodeCustomEvent*)>();
228 }
229 auto eventListenersSet = reinterpret_cast<std::set<void (*)(ArkUI_NodeCustomEvent*)>*>(
230 nodePtr->customEventListeners);
231 if (!eventListenersSet) {
232 return ERROR_CODE_PARAM_INVALID;
233 }
234 eventListenersSet->emplace(eventReceiver);
235 return ERROR_CODE_NO_ERROR;
236 }
237
RemoveNodeCustomEventReceiver(ArkUI_NodeHandle nodePtr,void (* eventReceiver)(ArkUI_NodeCustomEvent * event))238 int32_t RemoveNodeCustomEventReceiver(ArkUI_NodeHandle nodePtr,
239 void (*eventReceiver)(ArkUI_NodeCustomEvent* event))
240 {
241 if (!nodePtr || !eventReceiver || !nodePtr->customEventListeners || !CheckIsCNode(nodePtr)) {
242 return ERROR_CODE_PARAM_INVALID;
243 }
244 auto eventListenersSet = reinterpret_cast<std::set<void (*)(ArkUI_NodeCustomEvent*)>*>(
245 nodePtr->customEventListeners);
246 if (!eventListenersSet) {
247 return ERROR_CODE_PARAM_INVALID;
248 }
249 eventListenersSet->erase(eventReceiver);
250 if (eventListenersSet->empty()) {
251 delete eventListenersSet;
252 nodePtr->customEventListeners = nullptr;
253 }
254 return ERROR_CODE_NO_ERROR;
255 }
256
SetMeasuredSize(ArkUI_NodeHandle node,int32_t width,int32_t height)257 int32_t SetMeasuredSize(ArkUI_NodeHandle node, int32_t width, int32_t height)
258 {
259 if (node == nullptr || !CheckIsCNode(node)) {
260 return ERROR_CODE_PARAM_INVALID;
261 }
262 const auto* impl = GetFullImpl();
263 impl->getExtendedAPI()->setMeasureWidth(node->uiNodeHandle, width > 0 ? width : 0);
264 impl->getExtendedAPI()->setMeasureHeight(node->uiNodeHandle, height > 0 ? height : 0);
265 return ERROR_CODE_NO_ERROR;
266 }
267
SetLayoutPosition(ArkUI_NodeHandle node,int32_t positionX,int32_t positionY)268 int32_t SetLayoutPosition(ArkUI_NodeHandle node, int32_t positionX, int32_t positionY)
269 {
270 if (node == nullptr || !CheckIsCNode(node)) {
271 return ERROR_CODE_PARAM_INVALID;
272 }
273 const auto* impl = GetFullImpl();
274 impl->getExtendedAPI()->setX(node->uiNodeHandle, positionX);
275 impl->getExtendedAPI()->setY(node->uiNodeHandle, positionY);
276 return ERROR_CODE_NO_ERROR;
277 }
278
GetLayoutConstraint(ArkUI_NodeHandle node,ArkUI_LayoutConstraint * layoutConstraint)279 int32_t GetLayoutConstraint(ArkUI_NodeHandle node, ArkUI_LayoutConstraint* layoutConstraint)
280 {
281 if (node == nullptr || layoutConstraint == nullptr || !CheckIsCNode(node)) {
282 return ERROR_CODE_PARAM_INVALID;
283 }
284 const auto* impl = GetFullImpl();
285 // data size
286 ArkUI_Int32 data[6];
287 impl->getExtendedAPI()->getLayoutConstraint(node->uiNodeHandle, data);
288 //minWidth
289 layoutConstraint->minWidth = data[0];
290 //minHeight
291 layoutConstraint->minHeight = data[1];
292 //maxWidth
293 layoutConstraint->maxWidth = data[2];
294 //maxHeight
295 layoutConstraint->maxHeight = data[3];
296 //percentReferWidth
297 layoutConstraint->percentReferWidth = data[4];
298 //percentReferHeight
299 layoutConstraint->percentReferHeight = data[5];
300 return ERROR_CODE_NO_ERROR;
301 }
302
GetMeasuredSize(ArkUI_NodeHandle node)303 ArkUI_IntSize GetMeasuredSize(ArkUI_NodeHandle node)
304 {
305 ArkUI_IntSize size;
306 if (node == nullptr) {
307 return size;
308 }
309 const auto* impl = GetFullImpl();
310 size.width = impl->getExtendedAPI()->getMeasureWidth(node->uiNodeHandle);
311 size.height = impl->getExtendedAPI()->getMeasureHeight(node->uiNodeHandle);
312 return size;
313 }
314
GetLayoutPosition(ArkUI_NodeHandle node)315 ArkUI_IntOffset GetLayoutPosition(ArkUI_NodeHandle node)
316 {
317 ArkUI_IntOffset offset;
318 if (node == nullptr) {
319 return offset;
320 }
321 const auto* impl = GetFullImpl();
322 offset.x = impl->getExtendedAPI()->getX(node->uiNodeHandle);
323 offset.y = impl->getExtendedAPI()->getY(node->uiNodeHandle);
324 return offset;
325 }
326
MeasureNode(ArkUI_NodeHandle node,ArkUI_LayoutConstraint * constraint)327 int32_t MeasureNode(ArkUI_NodeHandle node, ArkUI_LayoutConstraint* constraint)
328 {
329 if (node == nullptr || constraint == nullptr || !CheckIsCNode(node)) {
330 return ERROR_CODE_PARAM_INVALID;
331 }
332 const auto* impl = GetFullImpl();
333 // data size
334 ArkUI_Float32 data[6];
335 //minWidth
336 data[0] = static_cast<ArkUI_Float32>(constraint->minWidth);
337 //minHeight
338 data[1] = static_cast<ArkUI_Float32>(constraint->minHeight);
339 //maxWidth
340 data[2] = static_cast<ArkUI_Float32>(constraint->maxWidth);
341 //maxHeight
342 data[3] = static_cast<ArkUI_Float32>(constraint->maxHeight);
343 //percentReferWidth
344 data[4] = static_cast<ArkUI_Float32>(constraint->percentReferWidth);
345 //percentReferHeight
346 data[5] = static_cast<ArkUI_Float32>(constraint->percentReferHeight);
347 impl->getExtendedAPI()->measureNode(nullptr, node->uiNodeHandle, data);
348 return ERROR_CODE_NO_ERROR;
349 }
350
LayoutNode(ArkUI_NodeHandle node,int32_t positionX,int32_t positionY)351 int32_t LayoutNode(ArkUI_NodeHandle node, int32_t positionX, int32_t positionY)
352 {
353 if (node == nullptr || !CheckIsCNode(node)) {
354 return ERROR_CODE_PARAM_INVALID;
355 }
356 const auto* impl = GetFullImpl();
357 //layout data size
358 float data[2];
359 //positionX
360 data[0] = positionX;
361 //positionY
362 data[1] = positionY;
363 impl->getExtendedAPI()->layoutNode(nullptr, node->uiNodeHandle, &data);
364 return ERROR_CODE_NO_ERROR;
365 }
366
GetTotalChildCount(ArkUI_NodeHandle node)367 uint32_t GetTotalChildCount(ArkUI_NodeHandle node)
368 {
369 if (node == nullptr) {
370 return 0;
371 }
372 const auto* impl = GetFullImpl();
373 return impl->getNodeModifiers()->getFrameNodeModifier()->getChildrenCount(node->uiNodeHandle, true);
374 }
375
GetChildAt(ArkUI_NodeHandle node,int32_t position)376 ArkUI_NodeHandle GetChildAt(ArkUI_NodeHandle node, int32_t position)
377 {
378 if (node == nullptr) {
379 return nullptr;
380 }
381 const auto* impl = GetFullImpl();
382 auto* attachNode = impl->getNodeModifiers()->getFrameNodeModifier()->getChild(node->uiNodeHandle, position, true);
383 return GetArkUINode(attachNode);
384 }
385
GetFirstChild(ArkUI_NodeHandle node)386 ArkUI_NodeHandle GetFirstChild(ArkUI_NodeHandle node)
387 {
388 if (node == nullptr) {
389 return nullptr;
390 }
391 const auto* impl = GetFullImpl();
392 auto* attachNode = impl->getNodeModifiers()->getFrameNodeModifier()->getFirst(node->uiNodeHandle, true);
393 return GetArkUINode(attachNode);
394 }
395
GetLastChild(ArkUI_NodeHandle node)396 ArkUI_NodeHandle GetLastChild(ArkUI_NodeHandle node)
397 {
398 if (node == nullptr) {
399 return nullptr;
400 }
401 const auto* impl = GetFullImpl();
402 auto* attachNode = impl->getNodeModifiers()->getFrameNodeModifier()->getLast(node->uiNodeHandle, true);
403 return GetArkUINode(attachNode);
404 }
405
GetPreviousSibling(ArkUI_NodeHandle node)406 ArkUI_NodeHandle GetPreviousSibling(ArkUI_NodeHandle node)
407 {
408 if (node == nullptr) {
409 return nullptr;
410 }
411 const auto* impl = GetFullImpl();
412 auto* attachNode = impl->getNodeModifiers()->getFrameNodeModifier()->getPreviousSibling(node->uiNodeHandle, true);
413 return GetArkUINode(attachNode);
414 }
415
GetNextSibling(ArkUI_NodeHandle node)416 ArkUI_NodeHandle GetNextSibling(ArkUI_NodeHandle node)
417 {
418 if (node == nullptr) {
419 return nullptr;
420 }
421 const auto* impl = GetFullImpl();
422 auto* attachNode = impl->getNodeModifiers()->getFrameNodeModifier()->getNextSibling(node->uiNodeHandle, true);
423 return GetArkUINode(attachNode);
424 }
425
GetParent(ArkUI_NodeHandle node)426 ArkUI_NodeHandle GetParent(ArkUI_NodeHandle node)
427 {
428 if (node == nullptr) {
429 return nullptr;
430 }
431 const auto* impl = GetFullImpl();
432 auto* value = impl->getNodeModifiers()->getFrameNodeModifier()->getParent(node->uiNodeHandle);
433 void* attachNode = impl->getExtendedAPI()->getAttachNodePtr(value);
434 if (attachNode) {
435 return reinterpret_cast<ArkUI_NodeHandle>(attachNode);
436 }
437 return nullptr;
438 }
439
RemoveAllChildren(ArkUI_NodeHandle parentNode)440 int32_t RemoveAllChildren(ArkUI_NodeHandle parentNode)
441 {
442 CHECK_NULL_RETURN(parentNode, ERROR_CODE_PARAM_INVALID);
443 const auto* impl = GetFullImpl();
444 impl->getNodeModifiers()->getFrameNodeModifier()->clearChildren(parentNode->uiNodeHandle);
445 return ERROR_CODE_NO_ERROR;
446 }
447 } // namespace OHOS::Ace::NodeModel
448