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 "core/interfaces/native/node/node_api.h"
17
18 #include <array>
19 #include <deque>
20
21 #include "base/log/log_wrapper.h"
22 #include "base/utils/macros.h"
23 #include "core/components_ng/base/frame_node.h"
24 #include "core/components_ng/base/ui_node.h"
25 #include "core/interfaces/arkoala/arkoala_api.h"
26 #include "core/interfaces/native/node/node_scroll_modifier.h"
27 #include "core/interfaces/native/node/node_text_input_modifier.h"
28 #include "core/interfaces/native/node/node_text_area_modifier.h"
29 #include "core/interfaces/native/node/node_toggle_modifier.h"
30 #include "core/interfaces/native/node/view_model.h"
31 #include "core/interfaces/native/node/node_common_modifier.h"
32 #include "core/interfaces/native/node/node_refresh_modifier.h"
33 #include "frameworks/core/common/container.h"
34
35 namespace OHOS::Ace::NG {
36
37 namespace NodeEvent {
38 std::deque<ArkUINodeEvent> g_eventQueue;
CheckEvent(ArkUINodeEvent * event)39 int CheckEvent(ArkUINodeEvent* event)
40 {
41 if (!g_eventQueue.empty()) {
42 *event = g_eventQueue.front();
43 g_eventQueue.pop_front();
44 return 1;
45 }
46 return 0;
47 }
48
49 void (*g_fliter)(ArkUINodeEvent* event) = nullptr;
SendArkUIAsyncEvent(ArkUINodeEvent * event)50 void SendArkUIAsyncEvent(ArkUINodeEvent* event)
51 {
52 if (g_fliter) {
53 g_fliter(event);
54 } else {
55 g_eventQueue.push_back(*event);
56 }
57 }
58 } // namespace NodeEvent
59
60 namespace {
61
CreateNode(ArkUINodeType type,int peerId,ArkUI_Int32)62 ArkUINodeHandle CreateNode(ArkUINodeType type, int peerId, ArkUI_Int32 /*flags*/)
63 {
64 return reinterpret_cast<ArkUINodeHandle>(ViewModel::CreateNode(type, peerId));
65 }
66
DisposeNode(ArkUINodeHandle node)67 void DisposeNode(ArkUINodeHandle node)
68 {
69 ViewModel::DisposeNode(node);
70 }
71
AddChild(ArkUINodeHandle parent,ArkUINodeHandle child)72 void AddChild(ArkUINodeHandle parent, ArkUINodeHandle child)
73 {
74 ViewModel::AddChild(parent, child);
75 }
76
RemoveChild(ArkUINodeHandle parent,ArkUINodeHandle child)77 void RemoveChild(ArkUINodeHandle parent, ArkUINodeHandle child)
78 {
79 ViewModel::RemoveChild(parent, child);
80 }
81
InsertChildAfter(ArkUINodeHandle parent,ArkUINodeHandle child,ArkUINodeHandle sibling)82 void InsertChildAfter(ArkUINodeHandle parent, ArkUINodeHandle child, ArkUINodeHandle sibling)
83 {
84 ViewModel::InsertChildAfter(parent, child, sibling);
85 }
86
87 typedef void (*ComponentAsyncEventHandler)(ArkUINodeHandle node, ArkUI_Int32 eventId, void* extraParam);
88
89 /**
90 * IMPORTANT!!!
91 * the order of declaring the handler must be same as the ArkUIAsyncEventKind did
92 */
93 /* clang-format off */
94 const ComponentAsyncEventHandler commonNodeAsyncEventHandlers[] = {
95 nullptr,
96 nullptr,
97 nullptr,
98 nullptr,
99 nullptr,
100 NodeModifier::SetOnBlur,
101 nullptr,
102 nullptr,
103 nullptr,
104 nullptr,
105 nullptr,
106 NodeModifier::SetOnFocus,
107 };
108
109 const ComponentAsyncEventHandler scrollNodeAsyncEventHandlers[] = {
110 NodeModifier::SetOnScroll,
111 NodeModifier::SetOnScrollFrameBegin,
112 NodeModifier::SetOnScrollStart,
113 NodeModifier::SetOnScrollStop,
114 NodeModifier::SetOnScrollEdge,
115 };
116
117 const ComponentAsyncEventHandler textInputNodeAsyncEventHandlers[] = {
118 nullptr,
119 NodeModifier::SetTextInputOnSubmit,
120 NodeModifier::SetOnTextInputChange,
121 };
122
123 const ComponentAsyncEventHandler textAreaNodeAsyncEventHandlers[] = {
124 nullptr,
125 nullptr,
126 NodeModifier::SetOnTextAreaChange,
127 };
128
129 const ComponentAsyncEventHandler refreshNodeAsyncEventHandlers[] = {
130 NodeModifier::SetRefreshOnStateChange,
131 NodeModifier::SetOnRefreshing,
132 };
133
134 const ComponentAsyncEventHandler TOGGLE_NODE_ASYNC_EVENT_HANDLERS[] = {
135 NodeModifier::SetOnToggleChange,
136 };
137
138 /* clang-format on */
NotifyComponentAsyncEvent(ArkUINodeHandle node,ArkUIAsyncEventKind kind,ArkUI_Int32 eventId,void * extraParam)139 void NotifyComponentAsyncEvent(ArkUINodeHandle node, ArkUIAsyncEventKind kind, ArkUI_Int32 eventId, void* extraParam)
140 {
141 unsigned int subClassType = kind / ARKUI_MAX_EVENT_NUM;
142 unsigned int subKind = kind % ARKUI_MAX_EVENT_NUM;
143 ComponentAsyncEventHandler eventHandle = nullptr;
144 switch (subClassType) {
145 case 0: {
146 // common event type.
147 if (subKind >= sizeof(commonNodeAsyncEventHandlers) / sizeof(ComponentAsyncEventHandler)) {
148 TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "NotifyComponentAsyncEvent kind:%{public}d NOT IMPLEMENT", kind);
149 return;
150 }
151 eventHandle = commonNodeAsyncEventHandlers[subKind];
152 break;
153 }
154 case ARKUI_SCROLL: {
155 // scroll event type.
156 if (subKind >= sizeof(scrollNodeAsyncEventHandlers) / sizeof(ComponentAsyncEventHandler)) {
157 TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "NotifyComponentAsyncEvent kind:%{public}d NOT IMPLEMENT", kind);
158 return;
159 }
160 eventHandle = scrollNodeAsyncEventHandlers[subKind];
161 break;
162 }
163 case ARKUI_TEXT_INPUT: {
164 // textinput event type.
165 if (subKind >= sizeof(textInputNodeAsyncEventHandlers) / sizeof(ComponentAsyncEventHandler)) {
166 TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "NotifyComponentAsyncEvent kind:%{public}d NOT IMPLEMENT", kind);
167 return;
168 }
169 eventHandle = textInputNodeAsyncEventHandlers[subKind];
170 break;
171 }
172 case ARKUI_TEXTAREA: {
173 // textarea event type.
174 if (subKind >= sizeof(textAreaNodeAsyncEventHandlers) / sizeof(ComponentAsyncEventHandler)) {
175 TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "NotifyComponentAsyncEvent kind:%{public}d NOT IMPLEMENT", kind);
176 return;
177 }
178 eventHandle = textAreaNodeAsyncEventHandlers[subKind];
179 break;
180 }
181 case ARKUI_REFRESH: {
182 // refresh event type.
183 if (subKind >= sizeof(refreshNodeAsyncEventHandlers) / sizeof(ComponentAsyncEventHandler)) {
184 TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "NotifyComponentAsyncEvent kind:%{public}d NOT IMPLEMENT", kind);
185 return;
186 }
187 eventHandle = refreshNodeAsyncEventHandlers[subKind];
188 break;
189 }
190 case ARKUI_TOGGLE: {
191 // toggle event type.
192 if (subKind >= sizeof(TOGGLE_NODE_ASYNC_EVENT_HANDLERS) / sizeof(ComponentAsyncEventHandler)) {
193 TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "NotifyComponentAsyncEvent kind:%{public}d NOT IMPLEMENT", kind);
194 return;
195 }
196 eventHandle = TOGGLE_NODE_ASYNC_EVENT_HANDLERS[subKind];
197 break;
198 }
199 default: {
200 TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "NotifyComponentAsyncEvent kind:%{public}d NOT IMPLEMENT", kind);
201 }
202 }
203 if (eventHandle) {
204 eventHandle(node, eventId, extraParam);
205 } else {
206 TAG_LOGE(AceLogTag::ACE_NATIVE_NODE, "NotifyComponentAsyncEvent kind:%{public}d EMPTY IMPLEMENT", kind);
207 }
208 }
209
NotifyResetComponentAsyncEvent(ArkUINodeHandle node,ArkUIAsyncEventKind subKind)210 void NotifyResetComponentAsyncEvent(ArkUINodeHandle node, ArkUIAsyncEventKind subKind)
211 {
212 // TODO
213 }
214
RegisterNodeAsyncEventReceiver(void (* eventReceiver)(ArkUINodeEvent * event))215 void RegisterNodeAsyncEventReceiver(void (*eventReceiver)(ArkUINodeEvent* event))
216 {
217 NodeEvent::g_fliter = eventReceiver;
218 }
219
ApplyModifierFinish(ArkUINodeHandle nodePtr)220 void ApplyModifierFinish(ArkUINodeHandle nodePtr)
221 {
222 auto* uiNode = reinterpret_cast<UINode*>(nodePtr);
223 auto* frameNode = AceType::DynamicCast<FrameNode>(uiNode);
224 if (frameNode) {
225 frameNode->MarkModifyDone();
226 }
227 }
228
MarkDirty(ArkUINodeHandle nodePtr,ArkUI_Uint32 flag)229 void MarkDirty(ArkUINodeHandle nodePtr, ArkUI_Uint32 flag)
230 {
231 auto* uiNode = reinterpret_cast<UINode*>(nodePtr);
232 if (uiNode) {
233 uiNode->MarkDirtyNode(flag);
234 }
235 }
236
237 static ArkUIAPICallbackMethod* callbacks = nullptr;
238
SetCallbackMethod(ArkUIAPICallbackMethod * method)239 static void SetCallbackMethod(ArkUIAPICallbackMethod* method)
240 {
241 callbacks = method;
242 }
243
GetBasicAPI()244 const ArkUIBasicAPI* GetBasicAPI()
245 {
246 /* clang-format off */
247 static const ArkUIBasicAPI basicImpl = {
248 CreateNode,
249 DisposeNode,
250 nullptr,
251 nullptr,
252
253 AddChild,
254 RemoveChild,
255 InsertChildAfter,
256 nullptr,
257 nullptr,
258 nullptr,
259
260 NotifyComponentAsyncEvent,
261 NotifyResetComponentAsyncEvent,
262 RegisterNodeAsyncEventReceiver,
263 nullptr,
264
265 nullptr,
266
267 ApplyModifierFinish,
268 MarkDirty,
269 };
270 /* clang-format on */
271
272 return &basicImpl;
273 }
274
275 /* clang-format off */
276 ArkUIExtendedNodeAPI impl_extended = {
277 ARKUI_EXTENDED_API_VERSION,
278
279 nullptr,
280 nullptr,
281
282 SetCallbackMethod,
283 nullptr,
284 nullptr,
285 nullptr,
286 nullptr,
287 nullptr,
288 nullptr,
289 nullptr,
290 nullptr,
291 nullptr,
292 nullptr,
293 nullptr,
294 nullptr,
295 nullptr,
296 nullptr,
297 nullptr,
298 nullptr,
299 nullptr,
300 nullptr,
301 nullptr,
302 nullptr,
303 };
304 /* clang-format on */
305
CanvasDrawRect(ArkUICanvasHandle canvas,ArkUI_Float32 left,ArkUI_Float32 top,ArkUI_Float32 right,ArkUI_Float32 bottom,ArkUIPaintHandle paint)306 void CanvasDrawRect(ArkUICanvasHandle canvas, ArkUI_Float32 left, ArkUI_Float32 top, ArkUI_Float32 right,
307 ArkUI_Float32 bottom, ArkUIPaintHandle paint)
308 {
309 TAG_LOGI(AceLogTag::ACE_NATIVE_NODE,
310 "DrawRect canvas=%{public}p [%{public}f, %{public}f, %{public}f, %{public}f]\n",
311 canvas, left, top, right, bottom);
312 }
313
GetCanvasAPI()314 const ArkUIGraphicsCanvas* GetCanvasAPI()
315 {
316 static const ArkUIGraphicsCanvas modifier = {
317 nullptr,
318 nullptr,
319 nullptr,
320 nullptr,
321 nullptr,
322 CanvasDrawRect,
323 nullptr
324 };
325 return &modifier;
326 }
327
328 struct DummyPaint {
329 ArkUI_Int32 color;
330 };
331
PaintMake()332 ArkUIPaintHandle PaintMake()
333 {
334 return reinterpret_cast<ArkUIPaintHandle>(new DummyPaint());
335 }
336
PaintFinalize(ArkUIPaintHandle paintPtr)337 void PaintFinalize(ArkUIPaintHandle paintPtr)
338 {
339 auto* paint = reinterpret_cast<DummyPaint*>(paintPtr);
340 delete paint;
341 }
342
GetPaintAPI()343 const ArkUIGraphicsPaint* GetPaintAPI()
344 {
345 static const ArkUIGraphicsPaint modifier = {
346 PaintMake,
347 PaintFinalize,
348 nullptr,
349 nullptr,
350 nullptr,
351 nullptr
352 };
353 return &modifier;
354 }
355
GetFontAPI()356 const ArkUIGraphicsFont* GetFontAPI()
357 {
358 static const ArkUIGraphicsFont modifier = {
359 nullptr,
360 };
361 return &modifier;
362 }
363
GetGraphicsAPI()364 const ArkUIGraphicsAPI* GetGraphicsAPI()
365 {
366 static const ArkUIGraphicsAPI api = {
367 ARKUI_NODE_GRAPHICS_API_VERSION,
368 SetCallbackMethod,
369 GetCanvasAPI,
370 GetPaintAPI,
371 GetFontAPI
372 };
373 return &api;
374 }
375
GetAnimationAPI()376 const ArkUIAnimation* GetAnimationAPI()
377 {
378 static const ArkUIAnimation modifier = {
379 nullptr,
380 nullptr,
381 nullptr,
382 };
383 return &modifier;
384 }
385
GetNavigationAPI()386 const ArkUINavigation* GetNavigationAPI()
387 {
388 static const ArkUINavigation modifier = {
389 nullptr,
390 nullptr,
391 };
392 return &modifier;
393 }
394
395
396 /* clang-format off */
397 ArkUIFullNodeAPI impl_full = {
398 ARKUI_NODE_API_VERSION,
399 SetCallbackMethod, // CallbackMethod
400 GetBasicAPI, // BasicAPI
401 GetArkUINodeModifiers, // NodeModifiers
402 GetAnimationAPI, // Animation
403 GetNavigationAPI, // Navigation
404 GetGraphicsAPI, // Graphics
405 };
406 /* clang-format on */
407 } // namespace
408
409 } // namespace OHOS::Ace::NG
410
411
412 extern "C" {
413
GetArkUIAnyFullNodeAPI(int version)414 ACE_FORCE_EXPORT ArkUIAnyAPI* GetArkUIAnyFullNodeAPI(int version)
415 {
416 switch (version) {
417 case ARKUI_NODE_API_VERSION:
418 return reinterpret_cast<ArkUIAnyAPI*>(&OHOS::Ace::NG::impl_full);
419 default: {
420 TAG_LOGE(OHOS::Ace::AceLogTag::ACE_NATIVE_NODE,
421 "Requested version %{public}d is not supported, we're version %{public}d", version,
422 ARKUI_NODE_API_VERSION);
423 return nullptr;
424 }
425 }
426 }
427
GetArkUIFullNodeAPI()428 const ArkUIFullNodeAPI* GetArkUIFullNodeAPI()
429 {
430 return &OHOS::Ace::NG::impl_full;
431 }
432
SendArkUIAsyncEvent(ArkUINodeEvent * event)433 void SendArkUIAsyncEvent(ArkUINodeEvent* event)
434 {
435 OHOS::Ace::NG::NodeEvent::SendArkUIAsyncEvent(event);
436 }
437
GetArkUIAPI(ArkUIAPIVariantKind kind,ArkUI_Int32 version)438 ACE_FORCE_EXPORT const ArkUIAnyAPI* GetArkUIAPI(ArkUIAPIVariantKind kind, ArkUI_Int32 version)
439 {
440 switch (kind) {
441 case ArkUIAPIVariantKind::BASIC: {
442 switch (version) {
443 case ARKUI_BASIC_API_VERSION:
444 return reinterpret_cast<const ArkUIAnyAPI*>(OHOS::Ace::NG::GetBasicAPI());
445 default: {
446 TAG_LOGE(OHOS::Ace::AceLogTag::ACE_NATIVE_NODE,
447 "Requested basic version %{public}d is not supported, we're version %{public}d\n",
448 version, ARKUI_BASIC_API_VERSION);
449
450 return nullptr;
451 }
452 }
453 }
454 case ArkUIAPIVariantKind::FULL: {
455 switch (version) {
456 case ARKUI_FULL_API_VERSION:
457 return reinterpret_cast<const ArkUIAnyAPI*>(&OHOS::Ace::NG::impl_full);
458 default: {
459 TAG_LOGE(OHOS::Ace::AceLogTag::ACE_NATIVE_NODE,
460 "Requested full version %{public}d is not supported, we're version %{public}d\n",
461 version, ARKUI_FULL_API_VERSION);
462
463 return nullptr;
464 }
465 }
466 }
467 case ArkUIAPIVariantKind::GRAPHICS: {
468 switch (version) {
469 case ARKUI_NODE_GRAPHICS_API_VERSION:
470 return reinterpret_cast<const ArkUIAnyAPI*>(OHOS::Ace::NG::GetGraphicsAPI());
471 default: {
472 TAG_LOGE(OHOS::Ace::AceLogTag::ACE_NATIVE_NODE,
473 "Requested graphics version %{public}d is not supported, we're version %{public}d\n",
474 version, ARKUI_NODE_GRAPHICS_API_VERSION);
475
476 return nullptr;
477 }
478 }
479 }
480 case ArkUIAPIVariantKind::EXTENDED: {
481 switch (version) {
482 case ARKUI_EXTENDED_API_VERSION:
483 return reinterpret_cast<const ArkUIAnyAPI*>(&OHOS::Ace::NG::impl_extended);
484 default: {
485 TAG_LOGE(OHOS::Ace::AceLogTag::ACE_NATIVE_NODE,
486 "Requested extended version %{public}d is not supported, we're version %{public}d\n",
487 version, ARKUI_EXTENDED_API_VERSION);
488
489 return nullptr;
490 }
491 }
492 }
493 default: {
494 TAG_LOGE(OHOS::Ace::AceLogTag::ACE_NATIVE_NODE,
495 "API kind %{public}d is not supported\n",
496 static_cast<int>(kind));
497
498 return nullptr;
499 }
500 }
501 }
502
provideEntryPoint(void)503 __attribute__((constructor)) static void provideEntryPoint(void)
504 {
505 #ifdef WINDOWS_PLATFORM
506 // mingw has no setenv :(.
507 static char entryPointString[64];
508 (void)snprintf(entryPointString, sizeof entryPointString, "__LIBACE_ENTRY_POINT=%llx",
509 static_cast<unsigned long long>(reinterpret_cast<uintptr_t>(&GetArkUIAPI)));
510 putenv(entryPointString);
511 #else
512 char entryPointString[64];
513 (void)snprintf(entryPointString, sizeof entryPointString, "%llx",
514 static_cast<unsigned long long>(reinterpret_cast<uintptr_t>(&GetArkUIAPI)));
515 setenv("__LIBACE_ENTRY_POINT", entryPointString, 1);
516 #endif
517 }
518 }