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