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