• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }