1 /*
2  * Copyright (c) 2023 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 
16 #include "node_model.h"
17 
18 #include <cstdint>
19 #include <set>
20 #include <unordered_map>
21 
22 #include "event_converter.h"
23 #include "interfaces/native/event/ui_input_event_impl.h"
24 #include "native_node.h"
25 #include "native_type.h"
26 #include "node_extened.h"
27 #include "style_modifier.h"
28 
29 #include "base/error/error_code.h"
30 #include "base/log/log_wrapper.h"
31 #include "base/utils/utils.h"
32 #include "core/interfaces/arkoala/arkoala_api.h"
33 
34 namespace OHOS::Ace::NodeModel {
35 namespace {
36 #if defined(WINDOWS_PLATFORM)
37 #include <windows.h>
38 // Here we need to find module where GetArkUINodeAPI()
39 // function is implemented.
FindModule()40 void* FindModule()
41 {
42     // To find from main exe
43     HMODULE result = nullptr;
44     const char libname[] = "libace_compatible.dll";
45     GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN, libname, &result);
46     if (result) {
47         return result;
48     }
49     TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "Cannot find module!");
50     return nullptr;
51 }
FindFunction(void * library,const char * name)52 void* FindFunction(void* library, const char* name)
53 {
54     return (void*)GetProcAddress(reinterpret_cast<HMODULE>(library), name);
55 }
56 #else
57 #include <dlfcn.h>
58 void* FindModule()
59 {
60     const char libname[] = "libace_compatible.z.so";
61     void* result = dlopen(libname, RTLD_LAZY | RTLD_LOCAL);
62     if (result) {
63         return result;
64     }
65     TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "Cannot load libace: %{public}s", dlerror());
66     return nullptr;
67 }
68 
69 void* FindFunction(void* library, const char* name)
70 {
71     return dlsym(library, name);
72 }
73 #endif
74 
75 ArkUIFullNodeAPI* impl = nullptr;
76 
InitialFullNodeImpl(int version)77 bool InitialFullNodeImpl(int version)
78 {
79     if (!impl) {
80         typedef ArkUIAnyAPI* (*GetAPI_t)(int);
81         GetAPI_t getAPI = nullptr;
82         void* module = FindModule();
83         if (module == nullptr) {
84             TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "fail to get module");
85             return false;
86         }
87         // Note, that RTLD_DEFAULT is ((void *) 0).
88         getAPI = reinterpret_cast<GetAPI_t>(FindFunction(module, "GetArkUIAnyFullNodeAPI"));
89         if (!getAPI) {
90             TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "Cannot find GetArkUIAnyFullNodeAPI()");
91             return false;
92         }
93 
94         impl = reinterpret_cast<ArkUIFullNodeAPI*>((*getAPI)(version));
95         if (!impl) {
96             TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "getAPI() returned null");
97             return false;
98         }
99 
100         if (impl->version != version) {
101             TAG_LOGE(AceLogTag::ACE_NATIVE_NODE,
102                 "API version mismatch: expected %{public}d, but get the version %{public}d", version, impl->version);
103             return false;
104         }
105     }
106 
107     impl->getBasicAPI()->registerNodeAsyncEventReceiver(OHOS::Ace::NodeModel::HandleInnerEvent);
108     impl->getExtendedAPI()->registerCustomNodeAsyncEventReceiver(OHOS::Ace::NodeModel::HandleInnerCustomEvent);
109     return true;
110 }
111 } // namespace
112 
GetFullImpl()113 ArkUIFullNodeAPI* GetFullImpl()
114 {
115     return impl;
116 }
117 
InitialFullImpl()118 bool InitialFullImpl()
119 {
120     return InitialFullNodeImpl(ARKUI_NODE_API_VERSION);
121 }
122 
123 struct InnerEventExtraParam {
124     int32_t targetId;
125     ArkUI_NodeHandle nodePtr;
126     void* userData;
127 };
128 
129 struct ExtraData {
130     std::unordered_map<int64_t, InnerEventExtraParam*> eventMap;
131 };
132 
133 std::set<ArkUI_NodeHandle> g_nodeSet;
134 
IsValidArkUINode(ArkUI_NodeHandle nodePtr)135 bool IsValidArkUINode(ArkUI_NodeHandle nodePtr)
136 {
137     if (!nodePtr || g_nodeSet.count(nodePtr) == 0) {
138         return false;
139     }
140     return true;
141 }
142 
CreateNode(ArkUI_NodeType type)143 ArkUI_NodeHandle CreateNode(ArkUI_NodeType type)
144 {
145     static const ArkUINodeType nodes[] = { ARKUI_CUSTOM, ARKUI_TEXT, ARKUI_SPAN, ARKUI_IMAGE_SPAN, ARKUI_IMAGE,
146         ARKUI_TOGGLE, ARKUI_LOADING_PROGRESS, ARKUI_TEXT_INPUT, ARKUI_TEXTAREA, ARKUI_BUTTON, ARKUI_PROGRESS,
147         ARKUI_CHECKBOX, ARKUI_XCOMPONENT, ARKUI_DATE_PICKER, ARKUI_TIME_PICKER, ARKUI_TEXT_PICKER,
148         ARKUI_CALENDAR_PICKER, ARKUI_SLIDER, ARKUI_RADIO, ARKUI_IMAGE_ANIMATOR, ARKUI_STACK, ARKUI_SWIPER,
149         ARKUI_SCROLL, ARKUI_LIST, ARKUI_LIST_ITEM, ARKUI_LIST_ITEM_GROUP, ARKUI_COLUMN, ARKUI_ROW, ARKUI_FLEX,
150         ARKUI_REFRESH, ARKUI_WATER_FLOW, ARKUI_FLOW_ITEM, ARKUI_RELATIVE_CONTAINER, ARKUI_GRID, ARKUI_GRID_ITEM,
151         ARKUI_CUSTOM_SPAN };
152     // already check in entry point.
153     uint32_t nodeType = type < MAX_NODE_SCOPE_NUM ? type : (type - MAX_NODE_SCOPE_NUM + BASIC_COMPONENT_NUM);
154     const auto* impl = GetFullImpl();
155     if (nodeType >= sizeof(nodes) / sizeof(ArkUINodeType)) {
156         TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "node type: %{public}d NOT IMPLEMENT", type);
157         return nullptr;
158     }
159 
160     ArkUI_Int32 id = ARKUI_AUTO_GENERATE_NODE_ID;
161     auto* uiNode = impl->getBasicAPI()->createNode(nodes[nodeType], id, ARKUI_NODE_FLAG_C);
162     if (!uiNode) {
163         TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "node type: %{public}d can not find in full impl", type);
164         return nullptr;
165     }
166     impl->getBasicAPI()->markDirty(uiNode, ARKUI_DIRTY_FLAG_ATTRIBUTE_DIFF);
167     ArkUI_Node* arkUINode = new ArkUI_Node({ type, uiNode, true });
168     impl->getExtendedAPI()->setAttachNodePtr(uiNode, reinterpret_cast<void*>(arkUINode));
169     g_nodeSet.emplace(arkUINode);
170     return arkUINode;
171 }
172 
DisposeNativeSource(ArkUI_NodeHandle nativePtr)173 void DisposeNativeSource(ArkUI_NodeHandle nativePtr)
174 {
175     CHECK_NULL_VOID(nativePtr);
176     if (!CheckIsCNode(nativePtr)) {
177         return;
178     }
179     if (nativePtr->customEventListeners) {
180         auto eventListenersSet = reinterpret_cast<std::set<void (*)(ArkUI_NodeCustomEvent*)>*>(
181         nativePtr->customEventListeners);
182         if (eventListenersSet) {
183             eventListenersSet->clear();
184         }
185         delete eventListenersSet;
186         nativePtr->customEventListeners = nullptr;
187     }
188     if (nativePtr->eventListeners) {
189         auto eventListenersSet = reinterpret_cast<std::set<void (*)(ArkUI_NodeEvent*)>*>(
190         nativePtr->eventListeners);
191         if (eventListenersSet) {
192             eventListenersSet->clear();
193         }
194         delete eventListenersSet;
195         nativePtr->eventListeners = nullptr;
196     }
197     if (nativePtr->areaChangeRadio) {
198         delete[] nativePtr->areaChangeRadio->value;
199         delete nativePtr->areaChangeRadio;
200         nativePtr->areaChangeRadio = nullptr;
201     }
202 }
203 
DisposeNode(ArkUI_NodeHandle nativePtr)204 void DisposeNode(ArkUI_NodeHandle nativePtr)
205 {
206     CHECK_NULL_VOID(nativePtr);
207     if (!CheckIsCNode(nativePtr)) {
208         return;
209     }
210     // already check in entry point.
211     const auto* impl = GetFullImpl();
212     impl->getBasicAPI()->disposeNode(nativePtr->uiNodeHandle);
213     DisposeNativeSource(nativePtr);
214     g_nodeSet.erase(nativePtr);
215     delete nativePtr;
216     nativePtr = nullptr;
217 }
218 
AddChild(ArkUI_NodeHandle parentNode,ArkUI_NodeHandle childNode)219 int32_t AddChild(ArkUI_NodeHandle parentNode, ArkUI_NodeHandle childNode)
220 {
221     CHECK_NULL_RETURN(parentNode, ERROR_CODE_PARAM_INVALID);
222     CHECK_NULL_RETURN(childNode, ERROR_CODE_PARAM_INVALID);
223     if (!CheckIsCNode(parentNode) || !CheckIsCNode(childNode)) {
224         return ERROR_CODE_NATIVE_IMPL_BUILDER_NODE_ERROR;
225     }
226     // already check in entry point.
227     if (parentNode->type == -1) {
228         return ERROR_CODE_NATIVE_IMPL_BUILDER_NODE_ERROR;
229     }
230     const auto* impl = GetFullImpl();
231     // already check in entry point.
232     impl->getBasicAPI()->addChild(parentNode->uiNodeHandle, childNode->uiNodeHandle);
233     impl->getBasicAPI()->markDirty(parentNode->uiNodeHandle, ARKUI_DIRTY_FLAG_MEASURE_BY_CHILD_REQUEST);
234     return ERROR_CODE_NO_ERROR;
235 }
236 
RemoveChild(ArkUI_NodeHandle parentNode,ArkUI_NodeHandle childNode)237 int32_t RemoveChild(ArkUI_NodeHandle parentNode, ArkUI_NodeHandle childNode)
238 {
239     CHECK_NULL_RETURN(parentNode, ERROR_CODE_PARAM_INVALID);
240     CHECK_NULL_RETURN(childNode, ERROR_CODE_PARAM_INVALID);
241     if (!CheckIsCNode(parentNode) || !CheckIsCNode(childNode)) {
242         return ERROR_CODE_NATIVE_IMPL_BUILDER_NODE_ERROR;
243     }
244     // already check in entry point.
245     if (parentNode->type == -1) {
246         return ERROR_CODE_NATIVE_IMPL_BUILDER_NODE_ERROR;
247     }
248     const auto* impl = GetFullImpl();
249     impl->getBasicAPI()->removeChild(parentNode->uiNodeHandle, childNode->uiNodeHandle);
250     impl->getBasicAPI()->markDirty(parentNode->uiNodeHandle, ARKUI_DIRTY_FLAG_MEASURE_BY_CHILD_REQUEST);
251     return ERROR_CODE_NO_ERROR;
252 }
253 
InsertChildAfter(ArkUI_NodeHandle parentNode,ArkUI_NodeHandle childNode,ArkUI_NodeHandle siblingNode)254 int32_t InsertChildAfter(ArkUI_NodeHandle parentNode, ArkUI_NodeHandle childNode, ArkUI_NodeHandle siblingNode)
255 {
256     CHECK_NULL_RETURN(parentNode, ERROR_CODE_PARAM_INVALID);
257     CHECK_NULL_RETURN(childNode, ERROR_CODE_PARAM_INVALID);
258     if (!CheckIsCNode(parentNode) || !CheckIsCNode(childNode)) {
259         return ERROR_CODE_NATIVE_IMPL_BUILDER_NODE_ERROR;
260     }
261     // already check in entry point.
262     if (parentNode->type == -1) {
263         return ERROR_CODE_NATIVE_IMPL_BUILDER_NODE_ERROR;
264     }
265     const auto* impl = GetFullImpl();
266     impl->getBasicAPI()->insertChildAfter(
267         parentNode->uiNodeHandle, childNode->uiNodeHandle, siblingNode ? siblingNode->uiNodeHandle : nullptr);
268     impl->getBasicAPI()->markDirty(parentNode->uiNodeHandle, ARKUI_DIRTY_FLAG_MEASURE_BY_CHILD_REQUEST);
269     return ERROR_CODE_NO_ERROR;
270 }
271 
InsertChildBefore(ArkUI_NodeHandle parentNode,ArkUI_NodeHandle childNode,ArkUI_NodeHandle siblingNode)272 int32_t InsertChildBefore(ArkUI_NodeHandle parentNode, ArkUI_NodeHandle childNode, ArkUI_NodeHandle siblingNode)
273 {
274     CHECK_NULL_RETURN(parentNode, ERROR_CODE_PARAM_INVALID);
275     CHECK_NULL_RETURN(childNode, ERROR_CODE_PARAM_INVALID);
276     if (!CheckIsCNode(parentNode) || !CheckIsCNode(childNode)) {
277         return ERROR_CODE_NATIVE_IMPL_BUILDER_NODE_ERROR;
278     }
279     // already check in entry point.
280     if (parentNode->type == -1) {
281         return ERROR_CODE_NATIVE_IMPL_BUILDER_NODE_ERROR;
282     }
283     const auto* impl = GetFullImpl();
284     impl->getBasicAPI()->insertChildBefore(
285         parentNode->uiNodeHandle, childNode->uiNodeHandle, siblingNode ? siblingNode->uiNodeHandle : nullptr);
286     impl->getBasicAPI()->markDirty(parentNode->uiNodeHandle, ARKUI_DIRTY_FLAG_MEASURE_BY_CHILD_REQUEST);
287     return ERROR_CODE_NO_ERROR;
288 }
289 
InsertChildAt(ArkUI_NodeHandle parentNode,ArkUI_NodeHandle childNode,int32_t position)290 int32_t InsertChildAt(ArkUI_NodeHandle parentNode, ArkUI_NodeHandle childNode, int32_t position)
291 {
292     CHECK_NULL_RETURN(parentNode, ERROR_CODE_PARAM_INVALID);
293     CHECK_NULL_RETURN(childNode, ERROR_CODE_PARAM_INVALID);
294     if (!CheckIsCNode(parentNode) || !CheckIsCNode(childNode)) {
295         return ERROR_CODE_NATIVE_IMPL_BUILDER_NODE_ERROR;
296     }
297     // already check in entry point.
298     if (parentNode->type == -1) {
299         return ERROR_CODE_NATIVE_IMPL_BUILDER_NODE_ERROR;
300     }
301     const auto* impl = GetFullImpl();
302     impl->getBasicAPI()->insertChildAt(parentNode->uiNodeHandle, childNode->uiNodeHandle, position);
303     impl->getBasicAPI()->markDirty(parentNode->uiNodeHandle, ARKUI_DIRTY_FLAG_MEASURE_BY_CHILD_REQUEST);
304     return ERROR_CODE_NO_ERROR;
305 }
306 
SetAttribute(ArkUI_NodeHandle node,ArkUI_NodeAttributeType attribute,const char * value)307 void SetAttribute(ArkUI_NodeHandle node, ArkUI_NodeAttributeType attribute, const char* value)
308 {
309     SetNodeAttribute(node, attribute, value);
310 }
311 
SetAttribute(ArkUI_NodeHandle node,ArkUI_NodeAttributeType attribute,const ArkUI_AttributeItem * value)312 int32_t SetAttribute(ArkUI_NodeHandle node, ArkUI_NodeAttributeType attribute, const ArkUI_AttributeItem* value)
313 {
314     if (node == nullptr) {
315         return ERROR_CODE_PARAM_INVALID;
316     }
317     if (node->type == -1 && attribute != NODE_LAYOUT_RECT) {
318         return ERROR_CODE_NATIVE_IMPL_BUILDER_NODE_ERROR;
319     }
320     return SetNodeAttribute(node, attribute, value);
321 }
322 
ResetAttribute(ArkUI_NodeHandle node,ArkUI_NodeAttributeType attribute)323 int32_t ResetAttribute(ArkUI_NodeHandle node, ArkUI_NodeAttributeType attribute)
324 {
325     if (node == nullptr) {
326         return ERROR_CODE_PARAM_INVALID;
327     }
328     if (node->type == -1 && attribute != NODE_LAYOUT_RECT) {
329         return ERROR_CODE_NATIVE_IMPL_BUILDER_NODE_ERROR;
330     }
331     return ResetNodeAttribute(node, attribute);
332 }
333 
GetAttribute(ArkUI_NodeHandle node,ArkUI_NodeAttributeType attribute)334 const ArkUI_AttributeItem* GetAttribute(ArkUI_NodeHandle node, ArkUI_NodeAttributeType attribute)
335 {
336     if (node == nullptr) {
337         return nullptr;
338     }
339     return GetNodeAttribute(node, attribute);
340 }
341 
RegisterNodeEvent(ArkUI_NodeHandle nodePtr,ArkUI_NodeEventType eventType,int32_t targetId)342 int32_t RegisterNodeEvent(ArkUI_NodeHandle nodePtr, ArkUI_NodeEventType eventType, int32_t targetId)
343 {
344     return RegisterNodeEvent(nodePtr, eventType, targetId, nullptr);
345 }
346 
RegisterNodeEvent(ArkUI_NodeHandle nodePtr,ArkUI_NodeEventType eventType,int32_t targetId,void * userData)347 int32_t RegisterNodeEvent(ArkUI_NodeHandle nodePtr, ArkUI_NodeEventType eventType, int32_t targetId, void* userData)
348 {
349     if (nodePtr == nullptr || !CheckIsCNode(nodePtr)) {
350         return ERROR_CODE_PARAM_INVALID;
351     }
352     auto originEventType = ConvertOriginEventType(eventType, nodePtr->type);
353     if (originEventType < 0) {
354         TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "event is not supported %{public}d", eventType);
355         return ERROR_CODE_NATIVE_IMPL_TYPE_NOT_SUPPORTED;
356     }
357     // already check in entry point.
358     if (nodePtr->type == -1) {
359         return ERROR_CODE_NATIVE_IMPL_BUILDER_NODE_ERROR;
360     }
361     const auto* impl = GetFullImpl();
362     auto* extraParam = new InnerEventExtraParam({ targetId, nodePtr, userData });
363     if (nodePtr->extraData) {
364         auto* extraData = reinterpret_cast<ExtraData*>(nodePtr->extraData);
365         auto result = extraData->eventMap.try_emplace(eventType, extraParam);
366         if (!result.second) {
367             result.first->second->targetId = targetId;
368             result.first->second->userData = userData;
369             delete extraParam;
370         }
371     } else {
372         nodePtr->extraData = new ExtraData();
373         auto* extraData = reinterpret_cast<ExtraData*>(nodePtr->extraData);
374         extraData->eventMap[eventType] = extraParam;
375     }
376     if (eventType == NODE_EVENT_ON_VISIBLE_AREA_CHANGE) {
377         ArkUI_AttributeItem* radio = nodePtr->areaChangeRadio;
378         radio = radio ? radio : static_cast<ArkUI_AttributeItem*>(userData);
379         if (!radio) {
380             return ERROR_CODE_PARAM_INVALID;
381         }
382         ArkUI_Int32 radioLength = radio->size;
383         if (radioLength <= 0) {
384             return ERROR_CODE_PARAM_INVALID;
385         }
386         ArkUI_Float32 radioList[radioLength];
387         for (int i = 0; i < radioLength; ++i) {
388             if (LessNotEqual(radio->value[i].f32, 0.0f) || GreatNotEqual(radio->value[i].f32, 1.0f)) {
389                 return ERROR_CODE_PARAM_INVALID;
390             }
391             radioList[i] = radio->value[i].f32;
392         }
393         impl->getNodeModifiers()->getCommonModifier()->setOnVisibleAreaChange(
394             nodePtr->uiNodeHandle, reinterpret_cast<int64_t>(nodePtr), radioList, radioLength);
395     } else {
396         impl->getBasicAPI()->registerNodeAsyncEvent(
397             nodePtr->uiNodeHandle, static_cast<ArkUIEventSubKind>(originEventType), reinterpret_cast<int64_t>(nodePtr));
398     }
399     return ERROR_CODE_NO_ERROR;
400 }
401 
UnregisterNodeEvent(ArkUI_NodeHandle nodePtr,ArkUI_NodeEventType eventType)402 void UnregisterNodeEvent(ArkUI_NodeHandle nodePtr, ArkUI_NodeEventType eventType)
403 {
404     if (nodePtr == nullptr || !CheckIsCNode(nodePtr)) {
405         return;
406     }
407     if (!nodePtr->extraData) {
408         return;
409     }
410     if (nodePtr->type == -1) {
411         return;
412     }
413     auto* extraData = reinterpret_cast<ExtraData*>(nodePtr->extraData);
414     auto& eventMap = extraData->eventMap;
415     auto innerEventExtraParam = eventMap.find(eventType);
416     if (innerEventExtraParam == eventMap.end()) {
417         return;
418     }
419     delete innerEventExtraParam->second;
420     eventMap.erase(innerEventExtraParam);
421     if (eventMap.empty()) {
422         delete extraData;
423         nodePtr->extraData = nullptr;
424     }
425     auto originEventType = ConvertOriginEventType(eventType, nodePtr->type);
426     if (originEventType < 0) {
427         return;
428     }
429     impl->getBasicAPI()->unRegisterNodeAsyncEvent(
430         nodePtr->uiNodeHandle, static_cast<ArkUIEventSubKind>(originEventType));
431 }
432 
433 void (*g_compatibleEventReceiver)(ArkUI_CompatibleNodeEvent* event) = nullptr;
RegisterOnEvent(void (* eventReceiver)(ArkUI_CompatibleNodeEvent * event))434 void RegisterOnEvent(void (*eventReceiver)(ArkUI_CompatibleNodeEvent* event))
435 {
436     g_compatibleEventReceiver = eventReceiver;
437 }
438 
439 void (*g_eventReceiver)(ArkUI_NodeEvent* event) = nullptr;
RegisterOnEvent(void (* eventReceiver)(ArkUI_NodeEvent * event))440 void RegisterOnEvent(void (*eventReceiver)(ArkUI_NodeEvent* event))
441 {
442     g_eventReceiver = eventReceiver;
443 }
444 
UnregisterOnEvent()445 void UnregisterOnEvent()
446 {
447     g_eventReceiver = nullptr;
448 }
449 
HandleTouchEvent(ArkUI_UIInputEvent & uiEvent,ArkUINodeEvent * innerEvent)450 void HandleTouchEvent(ArkUI_UIInputEvent& uiEvent, ArkUINodeEvent* innerEvent)
451 {
452     uiEvent.inputType = ARKUI_UIINPUTEVENT_TYPE_TOUCH;
453     uiEvent.eventTypeId = C_TOUCH_EVENT_ID;
454     uiEvent.inputEvent = &(innerEvent->touchEvent);
455 }
456 
HandleMouseEvent(ArkUI_UIInputEvent & uiEvent,ArkUINodeEvent * innerEvent)457 void HandleMouseEvent(ArkUI_UIInputEvent& uiEvent, ArkUINodeEvent* innerEvent)
458 {
459     uiEvent.inputType = ARKUI_UIINPUTEVENT_TYPE_MOUSE;
460     uiEvent.eventTypeId = C_MOUSE_EVENT_ID;
461     uiEvent.inputEvent = &(innerEvent->mouseEvent);
462 }
463 
HandleKeyEvent(ArkUI_UIInputEvent & uiEvent,ArkUINodeEvent * innerEvent)464 void HandleKeyEvent(ArkUI_UIInputEvent& uiEvent, ArkUINodeEvent* innerEvent)
465 {
466     uiEvent.eventTypeId = C_KEY_EVENT_ID;
467     uiEvent.inputEvent = &(innerEvent->keyEvent);
468 }
469 
HandleInnerNodeEvent(ArkUINodeEvent * innerEvent)470 void HandleInnerNodeEvent(ArkUINodeEvent* innerEvent)
471 {
472     if (!innerEvent) {
473         return;
474     }
475     auto nativeNodeEventType = GetNativeNodeEventType(innerEvent);
476     if (nativeNodeEventType == -1) {
477         return;
478     }
479     auto eventType = static_cast<ArkUI_NodeEventType>(nativeNodeEventType);
480     auto* nodePtr = reinterpret_cast<ArkUI_NodeHandle>(innerEvent->extraParam);
481     auto extraData = reinterpret_cast<ExtraData*>(nodePtr->extraData);
482     if (!extraData) {
483         return;
484     }
485     auto innerEventExtraParam = extraData->eventMap.find(eventType);
486     if (innerEventExtraParam == extraData->eventMap.end()) {
487         return;
488     }
489     ArkUI_NodeEvent event;
490     event.node = nodePtr;
491     event.eventId = innerEventExtraParam->second->targetId;
492     event.userData = innerEventExtraParam->second->userData;
493     if (!g_eventReceiver && !g_compatibleEventReceiver && (!(event.node) ||
494         (event.node && !(event.node->eventListeners)))) {
495         TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "event receiver is not register");
496         return;
497     }
498     if ((g_eventReceiver || (event.node && event.node->eventListeners))  && ConvertEvent(innerEvent, &event)) {
499         event.targetId = innerEvent->nodeId;
500         ArkUI_UIInputEvent uiEvent;
501         std::map<ArkUI_NodeEventType, std::function<void(ArkUI_UIInputEvent&, ArkUINodeEvent*)>> eventHandlers = {
502             {NODE_TOUCH_EVENT, HandleTouchEvent},
503             {NODE_ON_TOUCH_INTERCEPT, HandleTouchEvent},
504             {NODE_ON_MOUSE, HandleMouseEvent},
505             {NODE_ON_KEY_EVENT, HandleKeyEvent},
506             {NODE_ON_KEY_PRE_IME, HandleKeyEvent}
507         };
508 
509         auto it = eventHandlers.find(eventType);
510         if (it != eventHandlers.end()) {
511             it->second(uiEvent, innerEvent);
512             event.origin = &uiEvent;
513         } else {
514             event.origin = innerEvent;
515         }
516         HandleNodeEvent(&event);
517     }
518     if (g_compatibleEventReceiver) {
519         ArkUI_CompatibleNodeEvent event;
520         event.node = nodePtr;
521         event.eventId = innerEventExtraParam->second->targetId;
522         if (ConvertEvent(innerEvent, &event)) {
523             g_compatibleEventReceiver(&event);
524             ConvertEventResult(&event, innerEvent);
525         }
526     }
527 }
528 
GetNativeNodeEventType(ArkUINodeEvent * innerEvent)529 int32_t GetNativeNodeEventType(ArkUINodeEvent* innerEvent)
530 {
531     int32_t invalidType = -1;
532     auto* nodePtr = reinterpret_cast<ArkUI_NodeHandle>(innerEvent->extraParam);
533     if (!nodePtr || g_nodeSet.count(nodePtr) == 0) {
534         return invalidType;
535     }
536     if (!nodePtr->extraData) {
537         return invalidType;
538     }
539     auto extraData = reinterpret_cast<ExtraData*>(nodePtr->extraData);
540     ArkUIEventSubKind subKind = static_cast<ArkUIEventSubKind>(-1);
541     switch (innerEvent->kind) {
542         case COMPONENT_ASYNC_EVENT:
543             subKind = static_cast<ArkUIEventSubKind>(innerEvent->componentAsyncEvent.subKind);
544             break;
545         case TEXT_INPUT:
546             subKind = static_cast<ArkUIEventSubKind>(innerEvent->textInputEvent.subKind);
547             break;
548         case TOUCH_EVENT:
549             subKind = static_cast<ArkUIEventSubKind>(innerEvent->touchEvent.subKind);
550             break;
551         case MOUSE_INPUT_EVENT:
552             subKind = static_cast<ArkUIEventSubKind>(innerEvent->mouseEvent.subKind);
553             break;
554         case MIXED_EVENT:
555             subKind = static_cast<ArkUIEventSubKind>(innerEvent->mixedEvent.subKind);
556             break;
557         case DRAG_EVENT:
558             subKind = static_cast<ArkUIEventSubKind>(innerEvent->dragEvent.subKind);
559             break;
560         case KEY_INPUT_EVENT:
561             subKind = static_cast<ArkUIEventSubKind>(innerEvent->keyEvent.subKind);
562             break;
563         default:
564             break; /* Empty */
565     }
566     ArkUI_NodeEventType eventType = static_cast<ArkUI_NodeEventType>(ConvertToNodeEventType(subKind));
567     auto innerEventExtraParam = extraData->eventMap.find(eventType);
568     if (innerEventExtraParam == extraData->eventMap.end()) {
569         TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "the event of %{public}d is not register", eventType);
570         return invalidType;
571     }
572     return static_cast<int32_t>(eventType);
573 }
574 
HandleNodeEvent(ArkUI_NodeEvent * event)575 void HandleNodeEvent(ArkUI_NodeEvent* event)
576 {
577     if (!event) {
578         return;
579     }
580     if (event->node && event->node->eventListeners) {
581         auto eventListenersSet = reinterpret_cast<std::set<void (*)(ArkUI_NodeEvent*)>*>(event->node->eventListeners);
582         TriggerNodeEvent(event, eventListenersSet);
583     }
584     if (g_eventReceiver) {
585         g_eventReceiver(event);
586     }
587 }
588 
TriggerNodeEvent(ArkUI_NodeEvent * event,std::set<void (*)(ArkUI_NodeEvent *)> * eventListenersSet)589 void TriggerNodeEvent(ArkUI_NodeEvent* event, std::set<void (*)(ArkUI_NodeEvent*)>* eventListenersSet)
590 {
591     if (!eventListenersSet) {
592         return;
593     }
594     if (eventListenersSet->size() == 1) {
595         auto eventListener = eventListenersSet->begin();
596         (*eventListener)(event);
597     } else if (eventListenersSet->size() > 1) {
598         for (const auto& eventListener : *eventListenersSet) {
599             (*eventListener)(event);
600             if (!IsValidArkUINode(event->node)) {
601                 break;
602             }
603         }
604     }
605 }
606 
CheckEvent(ArkUI_NodeEvent * event)607 int32_t CheckEvent(ArkUI_NodeEvent* event)
608 {
609     return 0;
610 }
611 
SetUserData(ArkUI_NodeHandle node,void * userData)612 int32_t SetUserData(ArkUI_NodeHandle node, void* userData)
613 {
614     if (!node || !CheckIsCNode(node)) {
615         return ERROR_CODE_PARAM_INVALID;
616     }
617     if (!userData) {
618         return ERROR_CODE_PARAM_INVALID;
619     }
620     node->userData = userData;
621     return ERROR_CODE_NO_ERROR;
622 }
623 
GetUserData(ArkUI_NodeHandle node)624 void* GetUserData(ArkUI_NodeHandle node)
625 {
626     return node->userData;
627 }
628 
SetLengthMetricUnit(ArkUI_NodeHandle nodePtr,ArkUI_LengthMetricUnit unit)629 int32_t SetLengthMetricUnit(ArkUI_NodeHandle nodePtr, ArkUI_LengthMetricUnit unit)
630 {
631     if (!nodePtr || !CheckIsCNode(nodePtr)) {
632         return ERROR_CODE_PARAM_INVALID;
633     }
634     if (!InRegion(static_cast<int32_t>(ARKUI_LENGTH_METRIC_UNIT_DEFAULT),
635         static_cast<int32_t>(ARKUI_LENGTH_METRIC_UNIT_FP), static_cast<int32_t>(unit))) {
636         return ERROR_CODE_PARAM_INVALID;
637     }
638     nodePtr->lengthMetricUnit = unit;
639     return ERROR_CODE_NO_ERROR;
640 }
641 
ApplyModifierFinish(ArkUI_NodeHandle nodePtr)642 void ApplyModifierFinish(ArkUI_NodeHandle nodePtr)
643 {
644     // already check in entry point.
645     if (!nodePtr) {
646         return;
647     }
648     const auto* impl = GetFullImpl();
649     impl->getBasicAPI()->applyModifierFinish(nodePtr->uiNodeHandle);
650 }
651 
MarkDirty(ArkUI_NodeHandle nodePtr,ArkUI_NodeDirtyFlag dirtyFlag)652 void MarkDirty(ArkUI_NodeHandle nodePtr, ArkUI_NodeDirtyFlag dirtyFlag)
653 {
654     // spanNode inherited from UINode
655     if (!nodePtr || !CheckIsCNode(nodePtr)) {
656         return;
657     }
658     ArkUIDirtyFlag flag = ARKUI_DIRTY_FLAG_MEASURE;
659     switch (dirtyFlag) {
660         case NODE_NEED_MEASURE: {
661             flag = ARKUI_DIRTY_FLAG_MEASURE_SELF_AND_PARENT;
662             break;
663         }
664         case NODE_NEED_LAYOUT: {
665             flag = ARKUI_DIRTY_FLAG_LAYOUT;
666             break;
667         }
668         case NODE_NEED_RENDER: {
669             flag = ARKUI_DIRTY_FLAG_RENDER;
670             break;
671         }
672         default: {
673             flag = ARKUI_DIRTY_FLAG_MEASURE;
674         }
675     }
676     // already check in entry point.
677     const auto* impl = GetFullImpl();
678     impl->getBasicAPI()->markDirty(nodePtr->uiNodeHandle, flag);
679 }
680 
AddNodeEventReceiver(ArkUI_NodeHandle nodePtr,void (* eventReceiver)(ArkUI_NodeEvent * event))681 int32_t AddNodeEventReceiver(ArkUI_NodeHandle nodePtr, void (*eventReceiver)(ArkUI_NodeEvent* event))
682 {
683     if (!nodePtr || !eventReceiver || !CheckIsCNode(nodePtr)) {
684         return ERROR_CODE_PARAM_INVALID;
685     }
686     if (!nodePtr->eventListeners) {
687         nodePtr->eventListeners = new std::set<void (*)(ArkUI_NodeEvent*)>();
688     }
689     auto eventListenersSet = reinterpret_cast<std::set<void (*)(ArkUI_NodeEvent*)>*>(nodePtr->eventListeners);
690     if (!eventListenersSet) {
691         return ERROR_CODE_PARAM_INVALID;
692     }
693     eventListenersSet->emplace(eventReceiver);
694     return ERROR_CODE_NO_ERROR;
695 }
696 
RemoveNodeEventReceiver(ArkUI_NodeHandle nodePtr,void (* eventReceiver)(ArkUI_NodeEvent * event))697 int32_t RemoveNodeEventReceiver(ArkUI_NodeHandle nodePtr, void (*eventReceiver)(ArkUI_NodeEvent* event))
698 {
699     if (!nodePtr || !eventReceiver || !nodePtr->eventListeners || !CheckIsCNode(nodePtr)) {
700         return ERROR_CODE_PARAM_INVALID;
701     }
702     auto eventListenersSet = reinterpret_cast<std::set<void (*)(ArkUI_NodeEvent*)>*>(nodePtr->eventListeners);
703     if (!eventListenersSet) {
704         return ERROR_CODE_PARAM_INVALID;
705     }
706     eventListenersSet->erase(eventReceiver);
707     if (eventListenersSet->empty()) {
708         delete eventListenersSet;
709         nodePtr->eventListeners = nullptr;
710     }
711     return ERROR_CODE_NO_ERROR;
712 }
713 
GetParseJsMedia()714 void* GetParseJsMedia()
715 {
716     void* module = FindModule();
717     if (!module) {
718         TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "fail to get module");
719         return nullptr;
720     }
721     void (*parseJsMedia)(void* value, void* resource) = nullptr;
722     parseJsMedia = reinterpret_cast<void (*)(void*, void*)>(
723         FindFunction(module, "OHOS_ACE_ParseJsMedia"));
724     if (!parseJsMedia) {
725         TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "Cannot find OHOS_ACE_ParseJsMedia");
726         return nullptr;
727     }
728     return reinterpret_cast<void*>(parseJsMedia);
729 }
730 
CheckIsCNode(ArkUI_NodeHandle node)731 bool CheckIsCNode(ArkUI_NodeHandle node)
732 {
733     if (node->cNode || node->buildNode) {
734         return true;
735     }
736     return false;
737 }
738 } // namespace OHOS::Ace::NodeModel
739 
740 #ifdef __cplusplus
741 extern "C" {
742 #endif
743 
OH_ArkUI_NodeContent_AddNode(ArkUI_NodeContentHandle content,ArkUI_NodeHandle node)744 int32_t OH_ArkUI_NodeContent_AddNode(ArkUI_NodeContentHandle content, ArkUI_NodeHandle node)
745 {
746     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
747     CHECK_NULL_RETURN(impl, OHOS::Ace::ERROR_CODE_NATIVE_IMPL_LIBRARY_NOT_FOUND);
748     CHECK_NULL_RETURN(node, OHOS::Ace::ERROR_CODE_PARAM_INVALID);
749     return impl->getNodeModifiers()->getNodeContentModifier()->addChild(
750         reinterpret_cast<ArkUINodeContentHandle>(content), node->uiNodeHandle);
751 }
752 
OH_ArkUI_NodeContent_InsertNode(ArkUI_NodeContentHandle content,ArkUI_NodeHandle node,int32_t position)753 int32_t OH_ArkUI_NodeContent_InsertNode(ArkUI_NodeContentHandle content, ArkUI_NodeHandle node, int32_t position)
754 {
755     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
756     CHECK_NULL_RETURN(impl, OHOS::Ace::ERROR_CODE_NATIVE_IMPL_LIBRARY_NOT_FOUND);
757     CHECK_NULL_RETURN(node, OHOS::Ace::ERROR_CODE_PARAM_INVALID);
758     return impl->getNodeModifiers()->getNodeContentModifier()->insertChild(
759         reinterpret_cast<ArkUINodeContentHandle>(content), node->uiNodeHandle, position);
760 }
761 
OH_ArkUI_NodeContent_RemoveNode(ArkUI_NodeContentHandle content,ArkUI_NodeHandle node)762 int32_t OH_ArkUI_NodeContent_RemoveNode(ArkUI_NodeContentHandle content, ArkUI_NodeHandle node)
763 {
764     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
765     CHECK_NULL_RETURN(impl, OHOS::Ace::ERROR_CODE_NATIVE_IMPL_LIBRARY_NOT_FOUND);
766     CHECK_NULL_RETURN(node, OHOS::Ace::ERROR_CODE_PARAM_INVALID);
767     return impl->getNodeModifiers()->getNodeContentModifier()->removeChild(
768         reinterpret_cast<ArkUINodeContentHandle>(content), node->uiNodeHandle);
769 }
770 
OH_ArkUI_NodeContent_RegisterCallback(ArkUI_NodeContentHandle content,ArkUI_NodeContentCallback callback)771 int32_t OH_ArkUI_NodeContent_RegisterCallback(ArkUI_NodeContentHandle content, ArkUI_NodeContentCallback callback)
772 {
773     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
774     CHECK_NULL_RETURN(impl, OHOS::Ace::ERROR_CODE_NATIVE_IMPL_LIBRARY_NOT_FOUND);
775     auto innerCallback = reinterpret_cast<void (*)(ArkUINodeContentEvent* event)>(callback);
776     return impl->getNodeModifiers()->getNodeContentModifier()->registerEvent(
777         reinterpret_cast<ArkUINodeContentHandle>(content), nullptr, innerCallback);
778 }
779 
OH_ArkUI_NodeContentEvent_GetEventType(ArkUI_NodeContentEvent * event)780 ArkUI_NodeContentEventType OH_ArkUI_NodeContentEvent_GetEventType(ArkUI_NodeContentEvent* event)
781 {
782     CHECK_NULL_RETURN(event, static_cast<ArkUI_NodeContentEventType>(-1));
783     auto* innerEvent = reinterpret_cast<ArkUINodeContentEvent*>(event);
784     return static_cast<ArkUI_NodeContentEventType>(innerEvent->type);
785 }
786 
OH_ArkUI_NodeContentEvent_GetNodeContentHandle(ArkUI_NodeContentEvent * event)787 ArkUI_NodeContentHandle OH_ArkUI_NodeContentEvent_GetNodeContentHandle(ArkUI_NodeContentEvent* event)
788 {
789     CHECK_NULL_RETURN(event, nullptr);
790     auto* innerEvent = reinterpret_cast<ArkUINodeContentEvent*>(event);
791     return reinterpret_cast<ArkUI_NodeContentHandle>(innerEvent->nodeContent);
792 }
793 
OH_ArkUI_NodeContent_SetUserData(ArkUI_NodeContentHandle content,void * userData)794 int32_t OH_ArkUI_NodeContent_SetUserData(ArkUI_NodeContentHandle content, void* userData)
795 {
796     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
797     CHECK_NULL_RETURN(impl, OHOS::Ace::ERROR_CODE_NATIVE_IMPL_LIBRARY_NOT_FOUND);
798     return impl->getNodeModifiers()->getNodeContentModifier()->setUserData(
799         reinterpret_cast<ArkUINodeContentHandle>(content), userData);
800 }
801 
OH_ArkUI_NodeContent_GetUserData(ArkUI_NodeContentHandle content)802 void* OH_ArkUI_NodeContent_GetUserData(ArkUI_NodeContentHandle content)
803 {
804     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
805     CHECK_NULL_RETURN(impl, nullptr);
806     return impl->getNodeModifiers()->getNodeContentModifier()->getUserData(
807         reinterpret_cast<ArkUINodeContentHandle>(content));
808 }
809 
810 #ifdef __cplusplus
811 };
812 #endif
813