diff --git a/ArkUIKit/NdkXComponent/.gitignore b/ArkUIKit/NdkXComponent/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..fbabf771011fe78f9919db0b1195ab6cadffc2b0 --- /dev/null +++ b/ArkUIKit/NdkXComponent/.gitignore @@ -0,0 +1,11 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/AppScope/app.json5 b/ArkUIKit/NdkXComponent/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3179b1bfb4bb746f13ee7d4dd0fa58c3f66171cf --- /dev/null +++ b/ArkUIKit/NdkXComponent/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.samples.ndkxcomponent", + "vendor": "samples", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/ArkUIKit/NdkXComponent/AppScope/resources/base/element/string.json b/ArkUIKit/NdkXComponent/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..561383fbdef0dc2443f0cba3b1169289cb7a9ca0 --- /dev/null +++ b/ArkUIKit/NdkXComponent/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "NdkXComponent" + } + ] +} diff --git a/ArkUIKit/NdkXComponent/AppScope/resources/base/media/app_icon.png b/ArkUIKit/NdkXComponent/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/ArkUIKit/NdkXComponent/AppScope/resources/base/media/app_icon.png differ diff --git a/ArkUIKit/NdkXComponent/README_zh.md b/ArkUIKit/NdkXComponent/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..b2483cbf2c12a14d6eea66023b65e2031654d2f7 --- /dev/null +++ b/ArkUIKit/NdkXComponent/README_zh.md @@ -0,0 +1,117 @@ +# Native XComponent + +### 简介 + +本示例展示了如何在native侧使用ArkUI NDK API创建XComponent组件进行自定义绘制。具体步骤包括:创建组件,获取NativeXComponent实例,注册XComponent生命周期和事件回调,通过回调获取NativeWindow后使用OpenGL ES/EGL接口在XComponent组件上进行图形绘制,最后在ArkTS层使用ContentSlot站位组件进行挂载显示。功能主要包括点击按钮绘制一个五角星,并可以通过点击XComponent区域改变五角星的颜色。 + +### 效果预览 + +| 主页 | 绘制五角星 | 改变颜色 | +| ------------------------------------ | --------------------------------------------- | --------------------------------------------------- | +| ![main](screenshots/device/main.png) | ![draw star](screenshots/device/drawStar.png) | ![change color](screenshots/device/changeColor.png) | + +使用说明 + +1. 安装编译生成的hap包,并打开应用。 + +2. 点击页面底部“Draw Star”按钮,页面将绘制一个五角星。 + +3. 点击XComponent组件区域(页面中灰色区域)改变五角星颜色。 + + +### 工程目录 + +``` +├──entry/src/main +│ ├──cpp // C++代码区 +│ │ ├──CMakeLists.txt // CMake配置文件 +│ │ ├──napi_init.cpp // Napi模块注册 +│ │ ├──common +│ │ │ └──common.h // 常量定义文件 +│ │ ├──manager // 生命周期管理模块 +│ │ │ ├──plugin_manager.cpp +│ │ │ └──plugin_manager.h +│ │ ├──render // 渲染模块 +│ │ │ ├──egl_core.cpp +│ │ │ ├──egl_core.h +| | ├──types //定义接口文件 +│ │ │ ├──libnativenode +│ │ │ │ ├──Index.d.ts +│ │ │ │ ├──oh-package.json5 +│ ├──ets // ets代码区 +│ │ ├──entryability +│ │ │ └──EntryAbility.ts // 程序入口类 +│ │ └──pages // 页面文件 +│ │ └──Index.ets // 主界面 +| ├──resources // 资源文件目录 +``` + +### 具体实现 + +通过在IDE中创建Native c++ 工程,在c++代码中定义对外接口为drawPattern,在js侧调用该接口可在页面上绘制出一个三角形。 + +在XComponent的OnSurfaceCreated回调中获取NativeWindow实例并初始化EGL环境。调用OH_NativeXComponent_GetXComponentSize接口获取XComponent的宽高,并以此为输入调用EGL相关的绘制接口在NativeWindow上绘制出一个五角星。在DispatchTouchEvent回调中再次调用EGL相关的绘制接口在NativeWindow上绘制出一个大小相同、颜色不同的五角星,以达到点击后改变颜色的目的。 + +源码参考:[render目录](entry/src/main/cpp/render)下的文件。 + +涉及到的相关接口: + +| 接口名 | 描述 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | +| OH_NativeXComponent_GetXComponentId(OH_NativeXComponent* component, char* id, uint64_t* size) | 获取XComponent的id。 | +| OH_NativeXComponent_GetXComponentSize(OH_NativeXComponent* component, const void* window, uint64_t* width, uint64_t* height) | 获取XComponent持有的surface的大小。 | +| OH_NativeXComponent_GetXComponentOffset(OH_NativeXComponent* component, const void* window, double* x, double* y) | 获取XComponent持有的surface相对窗口左上角的偏移量。 | +| OH_NativeXComponent_GetTouchEvent(OH_NativeXComponent* component, const void* window, OH_NativeXComponent_TouchEvent* touchEvent) | 获取由XComponent触发的触摸事件。 | +| OH_NativeXComponent_GetTouchPointToolType(OH_NativeXComponent* component, uint32_t pointIndex, OH_NativeXComponent_TouchPointToolType* toolType) | 获取XComponent触摸点的工具类型。 | +| OH_NativeXComponent_GetTouchPointTiltX(OH_NativeXComponent* component, uint32_t pointIndex, float* tiltX) | 获取XComponent触摸点处相对X轴的倾斜角度。 | +| OH_NativeXComponent_GetTouchPointTiltY(OH_NativeXComponent* component, uint32_t pointIndex, float* tiltY) | 获取XComponent触摸点处相对Y轴的倾斜角度。 | +| OH_NativeXComponent_GetMouseEvent(OH_NativeXComponent* component, const void* window, OH_NativeXComponent_MouseEvent* mouseEvent) | 获取由XComponent触发的鼠标事件。 | +| OH_NativeXComponent_RegisterCallback(OH_NativeXComponent* component, OH_NativeXComponent_Callback* callback) | 为此OH_NativeXComponent实例注册生命周期和触摸事件回调。 | +| OH_NativeXComponent_RegisterMouseEventCallback(OH_NativeXComponent* component, OH_NativeXComponent_MouseEvent_Callback* callback) | 为此OH_NativeXComponent实例注册鼠标事件回调。 | +| OH_NativeXComponent_RegisterFocusEventCallback(OH_NativeXComponent* component, void (*callback)(OH_NativeXComponent* component, void* window)) | 为此OH_NativeXComponent实例注册获得焦点事件回调。 | +| OH_NativeXComponent_RegisterKeyEventCallback(OH_NativeXComponent* component, void (*callback)(OH_NativeXComponent* component, void* window)) | 为此OH_NativeXComponent实例注册按键事件回调。 | +| OH_NativeXComponent_RegisterBlurEventCallback(OH_NativeXComponent* component, void (*callback)(OH_NativeXComponent* component, void* window)) | 为此OH_NativeXComponent实例注册失去焦点事件回调。 | +| OH_NativeXComponent_GetKeyEvent(OH_NativeXComponent* component, OH_NativeXComponent_KeyEvent** keyEvent) | 获取由XComponent触发的按键事件。 | +| OH_NativeXComponent_GetKeyEventAction(OH_NativeXComponent_KeyEvent* keyEvent, OH_NativeXComponent_KeyAction* action) | 获取按键事件的动作。 | +| OH_NativeXComponent_GetKeyEventCode(OH_NativeXComponent_KeyEvent* keyEvent, OH_NativeXComponent_KeyCode* code) | 获取按键事件的键码值。 | +| OH_NativeXComponent_GetKeyEventSourceType(OH_NativeXComponent_KeyEvent* keyEvent, OH_NativeXComponent_EventSourceType* sourceType) | 获取按键事件的输入源类型。 | +| OH_NativeXComponent_GetKeyEventDeviceId(OH_NativeXComponent_KeyEvent* keyEvent, int64_t* deviceId) | 获取按键事件的设备ID。 | +| OH_NativeXComponent_GetKeyEventTimestamp(OH_NativeXComponent_KeyEvent* keyEvent, int64_t* timestamp) | 获取按键事件的时间戳。 | +| OH_ArkUI_QueryModuleInterfaceByName(ArkUI_NativeAPIVariantKind type, const char* structName) | 获取指定类型的Native模块接口集合。 | +| OH_ArkUI_GetNodeContentFromNapiValue(napi_env env, napi_value value, ArkUI_NodeContentHandle* content) | 获取ArkTS侧创建的NodeContent对象映射到native侧的ArkUI_NodeContentHandle。 | +| OH_ArkUI_NodeContent_SetUserData(ArkUI_NodeContentHandle content, void* userData) | 在NodeContent对象上保存自定义数据。 | +| OH_ArkUI_NodeContentEvent_GetNodeContentHandle(ArkUI_NodeContentEvent* event) | 获取触发事件的NodeContent对象。 | +| OH_ArkUI_NodeContent_GetUserData(ArkUI_NodeContentHandle content) | 获取在NodeContent对象上保存的自定义数据。 | +| OH_ArkUI_NodeContentEvent_GetEventType(ArkUI_NodeContentEvent* event) | 获取触发NodeContent事件的事件类型。 | +| OH_ArkUI_NodeContent_AddNode(ArkUI_NodeContentHandle content, ArkUI_NodeHandle node) | 将一个ArkUI组件节点添加到对应的NodeContent对象下。 | +| OH_ArkUI_NodeContent_RegisterCallback(ArkUI_NodeContentHandle content, ArkUI_NodeContentCallback callback) | 注册NodeContent事件函数。 | +| OH_NativeXComponent_GetNativeXComponent(ArkUI_NodeHandle node) | 基于Native接口创建的组件实例获取OH_NativeXComponent类型的指针。 | + +### 相关权限 + +不涉及。 + +### 依赖 + +不涉及。 + +### 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:RK3568 + +2. 本示例为Stage模型,支持API12版本SDK,SDK版本号(API Version 12Release),镜像版本号(5.0 Release) + +3. 本示例需要使用DevEco Studio 版本号(5.0 Release)及以上版本才可编译运行 + +### 下载 + +如需单独下载本工程,执行如下命令: + +``` +git init +git config core.sparsecheckout true +echo code/BasicFeature/Native/NdkXComponent/ > .git/info/sparse-checkout +git remote add origin https://gitee.com/openharmony/applications_app_samples.git +git pull origin master +``` + diff --git a/ArkUIKit/NdkXComponent/build-profile.json5 b/ArkUIKit/NdkXComponent/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..90ae14d97a40a1aa4788181816d740d771abf9e0 --- /dev/null +++ b/ArkUIKit/NdkXComponent/build-profile.json5 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.0.0(12)", + "runtimeOS": "HarmonyOS" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/.gitignore b/ArkUIKit/NdkXComponent/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/build-profile.json5 b/ArkUIKit/NdkXComponent/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..9432c50088f120b83eb0acef14e76327b8b30e29 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/build-profile.json5 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": 'stageMode', + "buildOption": { + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + "abiFilters": ["arm64-v8a", "x86_64"] + } + }, + "targets": [ + { + "name": "default", + "runtimeOS": "HarmonyOS" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/hvigorfile.ts b/ArkUIKit/NdkXComponent/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..80e4ec5b81689f238c34614b167a0b9e9c83e8d9 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/hvigorfile.ts @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +export { hapTasks } from '@ohos/hvigor-ohos-plugin'; diff --git a/ArkUIKit/NdkXComponent/entry/oh-package.json5 b/ArkUIKit/NdkXComponent/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a9801d3de62a442d58cb309ab82d06c7b6c1557d --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "license": "", + "devDependencies": {}, + "author": "", + "name": "entry", + "description": "Please describe the basic information.", + "main": "", + "version": "1.0.0", + "dependencies": { + "libnativenode.so": "file:./src/main/cpp/types/libnativenode" + } +} diff --git a/ArkUIKit/NdkXComponent/entry/src/main/cpp/CMakeLists.txt b/ArkUIKit/NdkXComponent/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7ce33599c512418862134501426894afcc20ac4b --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,68 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.4.1) +project(XComponent) + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +add_definitions(-DOHOS_PLATFORM) + +include_directories( + ${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/include +) + +add_library(nativenode SHARED + render/egl_core.cpp + manager/plugin_manager.cpp + napi_init.cpp +) + +find_library( + # Sets the name of the path variable. + EGL-lib + # Specifies the name of the NDK library that + # you want CMake to locate. + EGL +) + +find_library( + # Sets the name of the path variable. + GLES-lib + # Specifies the name of the NDK library that + # you want CMake to locate. + GLESv3 +) + +find_library( + # Sets the name of the path variable. + hilog-lib + # Specifies the name of the NDK library that + # you want CMake to locate. + hilog_ndk.z +) + +find_library( + # Sets the name of the path variable. + libace-lib + # Specifies the name of the NDK library that + # you want CMake to locate. + ace_ndk.z +) + +find_library( + # Sets the name of the path variable. + libnapi-lib + # Specifies the name of the NDK library that + # you want CMake to locate. + ace_napi.z +) + +find_library( + # Sets the name of the path variable. + libuv-lib + # Specifies the name of the NDK library that + # you want CMake to locate. + uv +) + +target_link_libraries(nativenode PUBLIC + ${EGL-lib} ${GLES-lib} ${hilog-lib} ${libace-lib} ${libnapi-lib} ${libuv-lib}) \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/main/cpp/common/common.h b/ArkUIKit/NdkXComponent/entry/src/main/cpp/common/common.h new file mode 100644 index 0000000000000000000000000000000000000000..c7760109da75f11204bd359ac3a65900b6749872 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/cpp/common/common.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NATIVE_XCOMPONENT_COMMON_H +#define NATIVE_XCOMPONENT_COMMON_H + +#include +#include +#include +#include +#include + +namespace NativeXComponentSample { +/** + * Log print domain. + */ +const unsigned int LOG_PRINT_DOMAIN = 0xFF00; +} // namespace NativeXComponentSample +#endif // NATIVE_XCOMPONENT_COMMON_H diff --git a/ArkUIKit/NdkXComponent/entry/src/main/cpp/manager/plugin_manager.cpp b/ArkUIKit/NdkXComponent/entry/src/main/cpp/manager/plugin_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e108a8c85195d7044c0bce006e8e3e67301f3352 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/cpp/manager/plugin_manager.cpp @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "plugin_manager.h" + +#include +#include +#include +#include +#include +#include "arkui/native_node.h" +#include "arkui/native_node_napi.h" +#include "arkui/native_interface.h" +#include "../common/common.h" + +#define COLUMN_MARGIN 10 +#define XC_WIDTH 300 +#define XC_HEIGHT 300 +#define ARG_CNT 2 + +namespace NativeXComponentSample { +PluginManager PluginManager::pluginManager_; +OH_NativeXComponent_Callback PluginManager::callback_; +static ArkUI_NativeNodeAPI_1* nodeAPI; +ArkUI_NodeHandle xc; +int32_t PluginManager::hasDraw_ = 0; +int32_t PluginManager::hasChangeColor_ = 0; + +static std::string value2String(napi_env env, napi_value value) +{ + size_t stringSize = 0; + napi_get_value_string_utf8(env, value, nullptr, 0, &stringSize); + std::string valueString; + valueString.resize(stringSize); + napi_get_value_string_utf8(env, value, &valueString[0], stringSize+1, &stringSize); + return valueString; +} +napi_value PluginManager::GetXComponentStatus(napi_env env, napi_callback_info info) +{ + napi_value hasDraw; + napi_value hasChangeColor; + + napi_status ret = napi_create_int32(env, hasDraw_, &(hasDraw)); + if (ret != napi_ok) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "GetXComponentStatus", "napi_create_int32 hasDraw_ error"); + return nullptr; + } + ret = napi_create_int32(env, hasChangeColor_, &(hasChangeColor)); + if (ret != napi_ok) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "GetXComponentStatus", "napi_create_int32 hasChangeColor_ error"); + return nullptr; + } + + napi_value obj; + ret = napi_create_object(env, &obj); + if (ret != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "GetXComponentStatus", "napi_create_object error"); + return nullptr; + } + ret = napi_set_named_property(env, obj, "hasDraw", hasDraw); + if (ret != napi_ok) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "GetXComponentStatus", "napi_set_named_property hasDraw error"); + return nullptr; + } + ret = napi_set_named_property(env, obj, "hasChangeColor", hasChangeColor); + if (ret != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "GetXComponentStatus", + "napi_set_named_property hasChangeColor error"); + return nullptr; + } + return obj; +} + +napi_value PluginManager::NapiDrawPattern(napi_env env, napi_callback_info info) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginManager", "NapiDrawPattern"); + if ((env == nullptr) || (info == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "NapiDrawPattern: env or info is null"); + return nullptr; + } + napi_value thisArg; + if (napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "NapiDrawPattern: napi_get_cb_info fail"); + return nullptr; + } + + auto *pluginManger = PluginManager::GetInstance(); + pluginManger->eglcore_->Draw(hasDraw_); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginManager", "render->eglCore_->Draw() executed"); + + return nullptr; +} + +void OnSurfaceCreatedCB(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceCreatedCB"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return; + } + + std::string id(idStr); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceCreatedCB id=%{public}s", + id.c_str()); + auto *pluginManger = PluginManager::GetInstance(); + pluginManger->OnSurfaceCreated(component, window); +} +void OnSurfaceChangedCB(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceChangedCB"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return; + } + std::string id(idStr); + auto *pluginManger = PluginManager::GetInstance(); + pluginManger->OnSurfaceChanged(component, window); +} +void OnSurfaceDestroyedCB(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceDestroyedCB"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return; + } + std::string id(idStr); + auto *pluginManger = PluginManager::GetInstance(); + pluginManger->OnSurfaceDestroyed(component, window); +} +void DispatchTouchEventCB(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "DispatchTouchEventCB"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return; + } + std::string id(idStr); + auto *pluginManger = PluginManager::GetInstance(); + pluginManger->DispatchTouchEvent(component, window); +} +PluginManager::PluginManager() +{ + eglcore_ = new EGLCore(); + callback_.OnSurfaceCreated = OnSurfaceCreatedCB; + callback_.OnSurfaceChanged = OnSurfaceChangedCB; + callback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB; + callback_.DispatchTouchEvent = DispatchTouchEventCB; +} + +PluginManager::~PluginManager() +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "~PluginManager"); + nativeXComponentMap_.clear(); + if (eglcore_ != nullptr) { + delete eglcore_; + eglcore_ = nullptr; + } + + for (auto iter = pluginManagerMap_.begin(); iter != pluginManagerMap_.end(); ++iter) { + if (iter->second != nullptr) { + delete iter->second; + iter->second = nullptr; + } + } + pluginManagerMap_.clear(); +} + +ArkUI_NodeHandle CreateNodeHandle(const std::string &tag) +{ + ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN); + ArkUI_NumberValue value[] = {480}; + ArkUI_NumberValue value1[] = {{.u32 = 15}, {.f32 = 15}}; + ArkUI_AttributeItem item = {value, 1, "changeSize"}; + ArkUI_AttributeItem item1 = {value1, 2}; + nodeAPI->setAttribute(column, NODE_WIDTH, &item); + value[0].f32 = COLUMN_MARGIN; + nodeAPI->setAttribute(column, NODE_MARGIN, &item); + xc = nodeAPI->createNode(ARKUI_NODE_XCOMPONENT); + value[0].u32 = ARKUI_XCOMPONENT_TYPE_SURFACE; + nodeAPI->setAttribute(xc, NODE_XCOMPONENT_TYPE, &item); + nodeAPI->setAttribute(xc, NODE_XCOMPONENT_ID, &item); + nodeAPI->setAttribute(xc, NODE_XCOMPONENT_SURFACE_SIZE, &item1); + ArkUI_NumberValue focusable[] = {1}; + focusable[0].i32 = 1; + ArkUI_AttributeItem focusableItem = {focusable, 1}; + nodeAPI->setAttribute(xc, NODE_FOCUSABLE, &focusableItem); + ArkUI_NumberValue valueSize[] = {480}; + ArkUI_AttributeItem itemSize = {valueSize, 1}; + valueSize[0].f32 = XC_WIDTH; + nodeAPI->setAttribute(xc, NODE_WIDTH, &itemSize); + valueSize[0].f32 = XC_HEIGHT; + nodeAPI->setAttribute(xc, NODE_HEIGHT, &itemSize); + ArkUI_AttributeItem item2 = {value, 1, "ndkxcomponent"}; + nodeAPI->setAttribute(xc, NODE_ID, &item2); + + auto *nativeXComponent = OH_NativeXComponent_GetNativeXComponent(xc); + if (!nativeXComponent) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "GetNativeXComponent error"); + return column; + } + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "GetNativeXComponent success"); + OH_NativeXComponent_RegisterCallback(nativeXComponent, &PluginManager::callback_); + auto typeRet = nodeAPI->getAttribute(xc, NODE_XCOMPONENT_TYPE); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "xcomponent type: %{public}d", + typeRet->value[0].i32); + auto idRet = nodeAPI->getAttribute(xc, NODE_XCOMPONENT_ID); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "xcomponent id: %{public}s", + idRet->string); + nodeAPI->addChild(column, xc); + return column; +} + +napi_value PluginManager::createNativeNode(napi_env env, napi_callback_info info) +{ + if ((env == nullptr) || (info == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "CreateNativeNode env or info is null"); + return nullptr; + } + size_t argCnt = 2; + napi_value args[2] = { nullptr, nullptr }; + if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "CreateNativeNode napi_get_cb_info failed"); + } + if (argCnt != ARG_CNT) { + napi_throw_type_error(env, NULL, "Wrong number of arguments"); + return nullptr; + } + ArkUI_NodeContentHandle nodeContentHandle_ = nullptr; + OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &nodeContentHandle_); + nodeAPI = reinterpret_cast( + OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1") + ); + std::string tag = value2String(env, args[1]); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "tag=%{public}s", tag.c_str()); + int32_t ret = OH_ArkUI_NodeContent_SetUserData(nodeContentHandle_, new std::string(tag)); + if (ret != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "setUserData failed error=%{public}d", ret); + } + if (nodeAPI != nullptr && nodeAPI->createNode != nullptr && nodeAPI->addChild != nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", + "CreateNativeNode tag=%{public}s", tag.c_str()); + auto nodeContentEvent = [](ArkUI_NodeContentEvent *event) { + ArkUI_NodeContentHandle handle = OH_ArkUI_NodeContentEvent_GetNodeContentHandle(event); + std::string *userDate = reinterpret_cast(OH_ArkUI_NodeContent_GetUserData(handle)); + if (OH_ArkUI_NodeContentEvent_GetEventType(event) == NODE_CONTENT_EVENT_ON_ATTACH_TO_WINDOW) { + ArkUI_NodeHandle testNode; + if (userDate) { + testNode = CreateNodeHandle(*userDate); + delete userDate; + userDate = nullptr; + } else { + testNode = CreateNodeHandle("noUserData"); + } + OH_ArkUI_NodeContent_AddNode(handle, testNode); + } + }; + OH_ArkUI_NodeContent_RegisterCallback(nodeContentHandle_, nodeContentEvent); + } + return nullptr; +} + +void PluginManager::OnSurfaceCreated(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "PluginManager::OnSurfaceCreated"); + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize); + ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_); + if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + eglcore_->EglContextInit(window, width_, height_); + eglcore_->Background(); + } +} + +void PluginManager::OnSurfaceDestroyed(OH_NativeXComponent* component, void* window) +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "PluginManager::OnSurfaceDestroyed"); +} + +void PluginManager::DispatchTouchEvent(OH_NativeXComponent* component, void* window) +{ + int32_t ret = OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent_); + if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + float tiltX = 2.2; + float tiltY = 2.2; + OH_NativeXComponent_TouchPointToolType toolType = + OH_NativeXComponent_TouchPointToolType::OH_NATIVEXCOMPONENT_TOOL_TYPE_LENS; + OH_NativeXComponent_GetTouchPointToolType(component, 0, &toolType); + OH_NativeXComponent_GetTouchPointTiltX(component, 0, &tiltX); + OH_NativeXComponent_GetTouchPointTiltY(component, 0, &tiltY); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", + "Touch Info : x=%{public}f, y=%{public}f screenx=%{public}f, screeny=%{public}f," + "type=%{public}d, force=%{public}f, tiltX=%{public}f, tiltY=%{public}f, toolType=%{public}d", + touchEvent_.x, touchEvent_.y, touchEvent_.screenX, + touchEvent_.screenY, touchEvent_.type, touchEvent_.force, tiltX, tiltY, toolType); + if (touchEvent_.type == OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_UP) + eglcore_->ChangeColor(hasChangeColor_); + } else { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "touch fail"); + } + + int32_t size = 0; + OH_NativeXComponent_HistoricalPoint *points = nullptr; + + if (OH_NativeXComponent_GetHistoricalPoints(component, window, &size, &points) == + OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "XComponent_Native", "HistoricalPoints size=%{public}d", + size); + for (auto i = 0; i < size; i++) { + auto point = points[i]; + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "XComponent_Native", + "HistoricalPoint %{public}d Info : id=%{public}d, x=%{public}f, y=%{public}f, " + "type=%{public}d, timeStamp=%{public}lld, sourceTool=%{public}d", + i, point.id, point.x, point.y, point.type, point.timeStamp, point.sourceTool); + } + } +} +void PluginManager::OnSurfaceChanged(OH_NativeXComponent* component, void* window) +{ + int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", + "OnSurfaceChanged ret=%{public}d width=%{public}lu, height=%{public}lu", ret, width_, height_); +} + +} // namespace NativeXComponentSample diff --git a/ArkUIKit/NdkXComponent/entry/src/main/cpp/manager/plugin_manager.h b/ArkUIKit/NdkXComponent/entry/src/main/cpp/manager/plugin_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..7bf51da76a22d2ef00a750a46e8b751469c2fffb --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/cpp/manager/plugin_manager.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef NATIVE_XCOMPONENT_PLUGIN_MANAGER_H +#define NATIVE_XCOMPONENT_PLUGIN_MANAGER_H + +#include +#include +#include +#include +#include +#include +#include +#include "render/egl_core.h" + +namespace NativeXComponentSample { +class PluginManager { +public: + + static OH_NativeXComponent_Callback callback_; + PluginManager(); + ~PluginManager(); + static PluginManager* GetInstance() + { + return &PluginManager::pluginManager_; + } + + static napi_value createNativeNode(napi_env env, napi_callback_info info); + static napi_value GetXComponentStatus(napi_env env, napi_callback_info info); + static napi_value NapiDrawPattern(napi_env env, napi_callback_info info); + + // CApi XComponent + void OnSurfaceChanged(OH_NativeXComponent* component, void* window); + void OnSurfaceDestroyed(OH_NativeXComponent* component, void* window); + void DispatchTouchEvent(OH_NativeXComponent* component, void* window); + void OnSurfaceCreated(OH_NativeXComponent* component, void* window); + +private: + static PluginManager pluginManager_; + std::unordered_map nativeXComponentMap_; + std::unordered_map pluginManagerMap_; + +public: + EGLCore *eglcore_; + uint64_t width_; + uint64_t height_; + OH_NativeXComponent_TouchEvent touchEvent_; + static int32_t hasDraw_; + static int32_t hasChangeColor_; +}; +} // namespace NativeXComponentSample +#endif // NATIVE_XCOMPONENT_PLUGIN_MANAGER_H diff --git a/ArkUIKit/NdkXComponent/entry/src/main/cpp/napi_init.cpp b/ArkUIKit/NdkXComponent/entry/src/main/cpp/napi_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..14df4224b95ffd042c9b36d55261c7fc91269f66 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/cpp/napi_init.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "common/common.h" +#include "manager/plugin_manager.h" + +namespace NativeXComponentSample { +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Init", "Init begins"); + if ((env == nullptr) || (exports == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Init", "env or exports is null"); + return nullptr; + } + + napi_property_descriptor desc[] = { + {"createNativeNode", nullptr, PluginManager::createNativeNode, nullptr, nullptr, nullptr, + napi_default, nullptr }, + {"getStatus", nullptr, PluginManager::GetXComponentStatus, nullptr, nullptr, + nullptr, napi_default, nullptr}, + {"drawPattern", nullptr, PluginManager::NapiDrawPattern, nullptr, nullptr, + nullptr, napi_default, nullptr} + }; + if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Init", "napi_define_properties failed"); + return nullptr; + } + + return exports; +} +EXTERN_C_END + +static napi_module nativenodeModule = { .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "nativenode", + .nm_priv = ((void*)0), + .reserved = { 0 } }; + +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&nativenodeModule); +} +} // namespace NativeXComponentSample diff --git a/ArkUIKit/NdkXComponent/entry/src/main/cpp/render/egl_core.cpp b/ArkUIKit/NdkXComponent/entry/src/main/cpp/render/egl_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..967d22ba58b7ebf7d3c8ca6ae994aeaf69bce28d --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/cpp/render/egl_core.cpp @@ -0,0 +1,611 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "egl_core.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "../common/common.h" + +namespace NativeXComponentSample { +namespace { +constexpr int32_t NUM_4 = 4; +/** + * Vertex shader. + */ +const char VERTEX_SHADER[] = "#version 300 es\n" + "layout(location = 0) in vec4 a_position;\n" + "layout(location = 1) in vec4 a_color; \n" + "out vec4 v_color; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " v_color = a_color; \n" + "} \n"; + +/** + * Fragment shader. + */ +const char FRAGMENT_SHADER[] = "#version 300 es\n" + "precision mediump float; \n" + "in vec4 v_color; \n" + "out vec4 fragColor; \n" + "void main() \n" + "{ \n" + " fragColor = v_color; \n" + "} \n"; + +/** + * Background color #f4f4f4. + */ +const GLfloat BACKGROUND_COLOR[] = {244.0f / 255, 244.0f / 255, 244.0f / 255, 1.0f}; + +/** + * Draw color #7E8FFB. + */ +const GLfloat DRAW_COLOR[] = {126.0f / 255, 143.0f / 255, 251.0f / 255, 1.0f}; + +/** + * Change color #92D6CC. + */ +const GLfloat CHANGE_COLOR[] = {146.0f / 255, 214.0f / 255, 204.0f / 255, 1.0f}; + +/** + * Background area. + */ +const GLfloat BACKGROUND_RECTANGLE_VERTICES[] = { + -1.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, -1.0f, + -1.0f, -1.0f}; + +/** + * Get context parameter count. + */ +const size_t GET_CONTEXT_PARAM_CNT = 1; + +/** + * Fifty percent. + */ +const float FIFTY_PERCENT = 0.5; + +/** + * Pointer size. + */ +const GLint POINTER_SIZE = 2; + +/** + * Triangle fan size. + */ +const GLsizei TRIANGLE_FAN_SIZE = 4; + +/** + * Egl red size default. + */ +const int EGL_RED_SIZE_DEFAULT = 8; + +/** + * Egl green size default. + */ +const int EGL_GREEN_SIZE_DEFAULT = 8; + +/** + * Egl blue size default. + */ +const int EGL_BLUE_SIZE_DEFAULT = 8; + +/** + * Egl alpha size default. + */ +const int EGL_ALPHA_SIZE_DEFAULT = 8; + +/** + * Default x position. + */ +const int DEFAULT_X_POSITION = 0; + +/** + * Default y position. + */ +const int DEFAULT_Y_POSITION = 0; + +/** + * Gl red default. + */ +const GLfloat GL_RED_DEFAULT = 0.0; + +/** + * Gl green default. + */ +const GLfloat GL_GREEN_DEFAULT = 0.0; + +/** + * Gl blue default. + */ +const GLfloat GL_BLUE_DEFAULT = 0.0; + +/** + * Gl alpha default. + */ +const GLfloat GL_ALPHA_DEFAULT = 1.0; + +/** + * Program error. + */ +const GLuint PROGRAM_ERROR = 0; + +/** + * Shape vertices size. + */ +const int SHAPE_VERTICES_SIZE = 8; + +/** + * Position handle name. + */ +const char POSITION_NAME[] = "a_position"; + +/** + * Position error. + */ +const GLint POSITION_ERROR = -1; + +/** + * Config attribute list. + */ +const EGLint ATTRIB_LIST[] = { + // Key,value. + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, EGL_RED_SIZE_DEFAULT, + EGL_GREEN_SIZE, EGL_GREEN_SIZE_DEFAULT, + EGL_BLUE_SIZE, EGL_BLUE_SIZE_DEFAULT, + EGL_ALPHA_SIZE, EGL_ALPHA_SIZE_DEFAULT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + // End. + EGL_NONE}; + +/** + * Context attributes. + */ +const EGLint CONTEXT_ATTRIBS[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE}; +} // namespace +bool EGLCore::EglContextInit(void* window, int width, int height) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "EglContextInit execute"); + if ((window == nullptr) || (width <= 0) || (height <= 0)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "EglContextInit: param error"); + return false; + } + + UpdateSize(width, height); + eglWindow_ = static_cast(window); + + // Init display. + eglDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (eglDisplay_ == EGL_NO_DISPLAY) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglGetDisplay: unable to get EGL display"); + return false; + } + + EGLint majorVersion; + EGLint minorVersion; + if (!eglInitialize(eglDisplay_, &majorVersion, &minorVersion)) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglInitialize: unable to get initialize EGL display"); + return false; + } + + // Select configuration. + const EGLint maxConfigSize = 1; + EGLint numConfigs; + if (!eglChooseConfig(eglDisplay_, ATTRIB_LIST, &eglConfig_, maxConfigSize, &numConfigs)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglChooseConfig: unable to choose configs"); + return false; + } + return CreateEnvironment(); +} + +bool EGLCore::CreateEnvironment() +{ + // Create surface. + if (eglWindow_ == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglWindow_ is null"); + return false; + } + eglSurface_ = eglCreateWindowSurface(eglDisplay_, eglConfig_, eglWindow_, NULL); + if (eglSurface_ == nullptr) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglCreateWindowSurface: unable to create surface"); + return false; + } + // Create context. + eglContext_ = eglCreateContext(eglDisplay_, eglConfig_, EGL_NO_CONTEXT, CONTEXT_ATTRIBS); + if (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglMakeCurrent failed"); + return false; + } + // Create program. + program_ = CreateProgram(VERTEX_SHADER, FRAGMENT_SHADER); + if (program_ == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "CreateProgram: unable to create program"); + return false; + } + return true; +} + +void EGLCore::Background() +{ + GLint position = PrepareDraw(); + if (position == POSITION_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background get position failed"); + return; + } + + if (!ExecuteDraw(position, BACKGROUND_COLOR, + BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background execute draw failed"); + return; + } + + if (!FinishDraw()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background FinishDraw failed"); + return; + } +} + +void EGLCore::Draw(int& hasDraw) +{ + flag_ = false; + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "Draw"); + GLint position = PrepareDraw(); + if (position == POSITION_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw get position failed"); + return; + } + + if (!ExecuteDraw(position, BACKGROUND_COLOR, + BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw background failed"); + return; + } + + // Divided into five quadrilaterals and calculate one of the quadrilateral's Vertices + GLfloat rotateX = 0; + GLfloat rotateY = FIFTY_PERCENT * height_; + GLfloat centerX = 0; + // Convert DEG(54° & 18°) to RAD + GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18); + // Convert DEG(18°) to RAD + GLfloat leftX = -rotateY * (M_PI / 180 * 18); + GLfloat leftY = 0; + // Convert DEG(18°) to RAD + GLfloat rightX = rotateY * (M_PI / 180 * 18); + GLfloat rightY = 0; + + const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_, + rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ }; + + if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed"); + return; + } + + // Convert DEG(72°) to RAD + GLfloat rad = M_PI / 180 * 72; + // Rotate four times + for (int i = 0; i < NUM_4; ++i) { + Rotate2d(centerX, centerY, &rotateX, &rotateY, rad); + Rotate2d(centerX, centerY, &leftX, &leftY, rad); + Rotate2d(centerX, centerY, &rightX, &rightY, rad); + + const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_, + rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ }; + + if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed"); + return; + } + } + + if (!FinishDraw()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw FinishDraw failed"); + return; + } + hasDraw = 1; + + flag_ = true; +} + +void EGLCore::ChangeColor(int& hasChangeColor) +{ + if (!flag_) { + return; + } + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor"); + GLint position = PrepareDraw(); + if (position == POSITION_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor get position failed"); + return; + } + + if (!ExecuteDraw(position, BACKGROUND_COLOR, + BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor execute draw background failed"); + return; + } + + // Divided into five quadrilaterals and calculate one of the quadrilateral's Vertices + GLfloat rotateX = 0; + GLfloat rotateY = FIFTY_PERCENT * height_; + GLfloat centerX = 0; + // Convert DEG(54° & 18°) to RAD + GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18); + // Convert DEG(18°) to RAD + GLfloat leftX = -rotateY * (M_PI / 180 * 18); + GLfloat leftY = 0; + // Convert DEG(18°) to RAD + GLfloat rightX = rotateY * (M_PI / 180 * 18); + GLfloat rightY = 0; + + const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_, + rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ }; + + if (!ExecuteDrawNewStar(0, CHANGE_COLOR, shapeVertices, sizeof(shapeVertices))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed"); + return; + } + + // Convert DEG(72°) to RAD + GLfloat rad = M_PI / 180 * 72; + // Rotate four times + for (int i = 0; i < NUM_4; ++i) { + Rotate2d(centerX, centerY, &rotateX, &rotateY, rad); + Rotate2d(centerX, centerY, &leftX, &leftY, rad); + Rotate2d(centerX, centerY, &rightX, &rightY, rad); + const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_, + rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ }; + + if (!ExecuteDrawNewStar(position, CHANGE_COLOR, shapeVertices, sizeof(shapeVertices))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed"); + return; + } + } + + if (!FinishDraw()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor FinishDraw failed"); + } + hasChangeColor = 1; +} + +GLint EGLCore::PrepareDraw() +{ + if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (eglContext_ == nullptr) || + (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "PrepareDraw: param error"); + return POSITION_ERROR; + } + + // The gl function has no return value. + glViewport(DEFAULT_X_POSITION, DEFAULT_Y_POSITION, width_, height_); + glClearColor(GL_RED_DEFAULT, GL_GREEN_DEFAULT, GL_BLUE_DEFAULT, GL_ALPHA_DEFAULT); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(program_); + + return glGetAttribLocation(program_, POSITION_NAME); +} + +bool EGLCore::ExecuteDraw(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize) +{ + if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error"); + return false; + } + + // The gl function has no return value. + glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices); + glEnableVertexAttribArray(position); + glVertexAttrib4fv(1, color); + glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE); + glDisableVertexAttribArray(position); + + return true; +} + +bool EGLCore::ExecuteDrawStar( + GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize) +{ + if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error"); + return false; + } + + // The gl function has no return value. + glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices); + glVertexAttribPointer(1, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, color); + glEnableVertexAttribArray(position); + glEnableVertexAttribArray(1); + glVertexAttrib4fv(1, color); + glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE); + glDisableVertexAttribArray(position); + glDisableVertexAttribArray(1); + + return true; +} + +bool EGLCore::ExecuteDrawNewStar( + GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize) +{ + if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error"); + return false; + } + + // The gl function has no return value. + glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices); + glEnableVertexAttribArray(position); + glVertexAttrib4fv(1, color); + glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE); + glDisableVertexAttribArray(position); + + return true; +} + +void EGLCore::Rotate2d(GLfloat centerX, GLfloat centerY, GLfloat* rotateX, GLfloat* rotateY, GLfloat theta) +{ + GLfloat tempX = cos(theta) * (*rotateX - centerX) - sin(theta) * (*rotateY - centerY); + GLfloat tempY = sin(theta) * (*rotateX - centerX) + cos(theta) * (*rotateY - centerY); + *rotateX = tempX + centerX; + *rotateY = tempY + centerY; +} + +bool EGLCore::FinishDraw() +{ + // The gl function has no return value. + glFlush(); + glFinish(); + return eglSwapBuffers(eglDisplay_, eglSurface_); +} + +GLuint EGLCore::LoadShader(GLenum type, const char* shaderSrc) +{ + if ((type <= 0) || (shaderSrc == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCreateShader type or shaderSrc error"); + return PROGRAM_ERROR; + } + + GLuint shader = glCreateShader(type); + if (shader == 0) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCreateShader unable to load shader"); + return PROGRAM_ERROR; + } + + // The gl function has no return value. + glShaderSource(shader, 1, &shaderSrc, nullptr); + glCompileShader(shader); + + GLint compiled; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (compiled != 0) { + return shader; + } + + GLint infoLen = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen <= 1) { + glDeleteShader(shader); + return PROGRAM_ERROR; + } + + char* infoLog = (char*)malloc(sizeof(char) * (infoLen + 1)); + if (infoLog != nullptr) { + memset(infoLog, 0, infoLen + 1); + glGetShaderInfoLog(shader, infoLen, nullptr, infoLog); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCompileShader error = %s", infoLog); + free(infoLog); + infoLog = nullptr; + } + glDeleteShader(shader); + return PROGRAM_ERROR; +} + +GLuint EGLCore::CreateProgram(const char* vertexShader, const char* fragShader) +{ + if ((vertexShader == nullptr) || (fragShader == nullptr)) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram: vertexShader or fragShader is null"); + return PROGRAM_ERROR; + } + + GLuint vertex = LoadShader(GL_VERTEX_SHADER, vertexShader); + if (vertex == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram vertex error"); + return PROGRAM_ERROR; + } + + GLuint fragment = LoadShader(GL_FRAGMENT_SHADER, fragShader); + if (fragment == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram fragment error"); + return PROGRAM_ERROR; + } + + GLuint program = glCreateProgram(); + if (program == PROGRAM_ERROR) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram program error"); + glDeleteShader(vertex); + glDeleteShader(fragment); + return PROGRAM_ERROR; + } + + // The gl function has no return value. + glAttachShader(program, vertex); + glAttachShader(program, fragment); + glLinkProgram(program); + + GLint linked; + glGetProgramiv(program, GL_LINK_STATUS, &linked); + if (linked != 0) { + glDeleteShader(vertex); + glDeleteShader(fragment); + return program; + } + + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram linked error"); + GLint infoLen = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) { + char* infoLog = (char*)malloc(sizeof(char) * (infoLen + 1)); + memset(infoLog, 0, infoLen + 1); + glGetProgramInfoLog(program, infoLen, nullptr, infoLog); + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glLinkProgram error = %s", infoLog); + free(infoLog); + infoLog = nullptr; + } + glDeleteShader(vertex); + glDeleteShader(fragment); + glDeleteProgram(program); + return PROGRAM_ERROR; +} + +void EGLCore::UpdateSize(int width, int height) +{ + width_ = width; + height_ = height; + if (width_ > 0) { + widthPercent_ = FIFTY_PERCENT * height_ / width_; + } +} + +void EGLCore::Release() +{ + if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (!eglDestroySurface(eglDisplay_, eglSurface_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroySurface failed"); + } + + if ((eglDisplay_ == nullptr) || (eglContext_ == nullptr) || (!eglDestroyContext(eglDisplay_, eglContext_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroyContext failed"); + } + + if ((eglDisplay_ == nullptr) || (!eglTerminate(eglDisplay_))) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglTerminate failed"); + } +} +} // namespace NativeXComponentSample diff --git a/ArkUIKit/NdkXComponent/entry/src/main/cpp/render/egl_core.h b/ArkUIKit/NdkXComponent/entry/src/main/cpp/render/egl_core.h new file mode 100644 index 0000000000000000000000000000000000000000..2bdc12a841056168ba4906a09d07246c495e860d --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/cpp/render/egl_core.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef NATIVE_XCOMPONENT_EGL_CORE_H +#define NATIVE_XCOMPONENT_EGL_CORE_H + +#include +#include +#include +#include "string" + +namespace NativeXComponentSample { +class EGLCore { +public: + explicit EGLCore() {} + ~EGLCore() {} + bool EglContextInit(void* window, int width, int height); + bool CreateEnvironment(); + void Draw(int& hasDraw); + void Background(); + void ChangeColor(int& hasChangeColor); + void Release(); + void UpdateSize(int width, int height); + +private: + GLuint LoadShader(GLenum type, const char* shaderSrc); + GLuint CreateProgram(const char* vertexShader, const char* fragShader); + GLint PrepareDraw(); + bool ExecuteDraw(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize); + bool ExecuteDrawStar(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize); + bool ExecuteDrawNewStar(GLint position, const GLfloat* color, + const GLfloat shapeVertices[], unsigned long vertSize); + void Rotate2d(GLfloat centerX, GLfloat centerY, GLfloat* rotateX, GLfloat* rotateY, GLfloat theta); + bool FinishDraw(); + +private: + EGLNativeWindowType eglWindow_; + EGLDisplay eglDisplay_ = EGL_NO_DISPLAY; + EGLConfig eglConfig_ = EGL_NO_CONFIG_KHR; + EGLSurface eglSurface_ = EGL_NO_SURFACE; + EGLContext eglContext_ = EGL_NO_CONTEXT; + GLuint program_; + bool flag_ = false; + int width_; + int height_; + GLfloat widthPercent_; +}; +} // namespace NativeXComponentSample +#endif // NATIVE_XCOMPONENT_EGL_CORE_H diff --git a/ArkUIKit/NdkXComponent/entry/src/main/cpp/types/libnativenode/Index.d.ts b/ArkUIKit/NdkXComponent/entry/src/main/cpp/types/libnativenode/Index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..8678295f391b4e7ef6159f95f5a2ee1d5cfb5d98 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/cpp/types/libnativenode/Index.d.ts @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NodeContent } from '@ohos.arkui.node'; +type XComponentContextStatus = { + hasDraw: boolean, + hasChangeColor: boolean +}; +export const createNativeNode: (content: NodeContent, tag: string) => void; +export const getStatus: () => XComponentContextStatus; +export const drawPattern: () => void; \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/main/cpp/types/libnativenode/oh-package.json5 b/ArkUIKit/NdkXComponent/entry/src/main/cpp/types/libnativenode/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d6c80337d1f0f9e37fd29bb98d74fd4260e1f467 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/cpp/types/libnativenode/oh-package.json5 @@ -0,0 +1,6 @@ +{ + "name": "libnativenode.so", + "types": "./Index.d.ts", + "version": " ", + "description": "Please describe the basic infomation" +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/main/ets/entryability/EntryAbility.ts b/ArkUIKit/NdkXComponent/entry/src/main/ets/entryability/EntryAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..aefdd5b7b8cf82af003c29651f07d7c7412d6060 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/ets/entryability/EntryAbility.ts @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import UIAbility from '@ohos.app.ability.UIAbility'; +import hilog from '@ohos.hilog'; +import window from '@ohos.window'; + +export default class EntryAbility extends UIAbility { + onCreate(want, launchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage) { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground() { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground() { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +}; diff --git a/ArkUIKit/NdkXComponent/entry/src/main/ets/pages/Index.ets b/ArkUIKit/NdkXComponent/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..4b1dfca47f5b09bb64510edb856801974991bd87 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import nativeNode from 'libnativenode.so'; +import {NodeContent} from '@kit.ArkUI'; + +@Entry +@Component +struct Index { + @State currentStatus: string = "init"; + private nodeContent: NodeContent = new NodeContent(); + aboutToAppear():void{ + nativeNode.createNativeNode(this.nodeContent,"ygb"); + } + + build() { + Column() { + Row() { + Text('Native XComponent Sample') + .fontSize('24fp') + .fontWeight(500) + .margin({ + left: 24, + top: 12 + }) + } + .margin({ top: 24 }) + .width('100%') + .height(56) + + Column({ space: 10 }) { + ContentSlot(this.nodeContent); + + Text(this.currentStatus) + .fontSize('24fp') + .fontWeight(500) + } + .onClick(() => { + let hasChangeColor: boolean = false; + if (nativeNode.getStatus()) { + hasChangeColor = nativeNode.getStatus().hasChangeColor; + } + if (hasChangeColor) { + this.currentStatus = "change color"; + } + }) + .margin({ + top: 27, + left: 12, + right: 12 + }) + .height('40%') + .width('90%') + + Row() { + Button('Draw Star') + .fontSize('16fp') + .fontWeight(500) + .margin({ bottom: 24 }) + .onClick(() => { + nativeNode.drawPattern(); + let hasDraw: boolean = false; + if (nativeNode.getStatus()) { + hasDraw = nativeNode.getStatus().hasDraw; + } + if (hasDraw) { + this.currentStatus = "draw star"; + } + }) + .width('53.6%') + .height(40) + } + .width('100%') + .justifyContent(FlexAlign.Center) + .alignItems(VerticalAlign.Bottom) + .layoutWeight(1) + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/main/module.json5 b/ArkUIKit/NdkXComponent/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..278546ed77ae8ab5a4f345a887e9abc332ceee6c --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/module.json5 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ts", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/main/resources/base/element/color.json b/ArkUIKit/NdkXComponent/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/main/resources/base/element/string.json b/ArkUIKit/NdkXComponent/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/main/resources/base/media/icon.png b/ArkUIKit/NdkXComponent/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/ArkUIKit/NdkXComponent/entry/src/main/resources/base/media/icon.png differ diff --git a/ArkUIKit/NdkXComponent/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/NdkXComponent/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/ArkUIKit/NdkXComponent/entry/src/main/resources/en_US/element/string.json b/ArkUIKit/NdkXComponent/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/main/resources/zh_CN/element/string.json b/ArkUIKit/NdkXComponent/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..597ecf95e61d7e30367c22fe2f8638008361b044 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts b/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts new file mode 100644 index 0000000000000000000000000000000000000000..585a000d65aaf0cc128e3e9edde5d7bbd9cb7d88 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import hilog from '@ohos.hilog'; +import TestRunner from '@ohos.application.testRunner'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + +let abilityDelegator = undefined; +let abilityDelegatorArguments = undefined; + +async function onAbilityCreateCallback() { + hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); + } + + async onRun() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments(); + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + let testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility'; + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback); + let cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName; + let debug = abilityDelegatorArguments.parameters['-D']; + if (debug == 'true') { + cmd += ' -D'; + } + hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd); + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? ''); + }); + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/test/List.test.ets b/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..e790e436bfe740d121e5b33d150ef2ab22da6158 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import abilityTest from './XComponentAbility.test' + +export default function testsuite() { + abilityTest() +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/test/XComponentAbility.test.ets b/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/test/XComponentAbility.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..948bfdc6020efdf89bf70e2e453fe1afa8ceb52e --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/test/XComponentAbility.test.ets @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { describe, it, expect } from '@ohos/hypium'; +import { Driver, ON } from '@ohos.UiTest'; + +const TAG = '[Sample_NDK_XComponent]'; + +export default function abilityTest() { + + describe('ActsAbilityTest', () => { + /** + * 打开应用 + */ + it('StartAbility_001', 0, async (done: Function) => { + console.info(TAG, 'StartAbility_001 begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.samples.ndkxcomponent', + abilityName: 'EntryAbility' + }); + } catch (exception) { + console.info(TAG, `StartAbility_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Draw Star')); + done(); + console.info(TAG, 'StartAbility_001 end'); + }) + + /** + * 点击按钮,绘制图形,之后点击XComponent改变颜色 + */ + it('DrawShape_001', 2, async () => { + console.info(TAG, 'CreateFiles_001 begin'); + let driver = Driver.create(); + // 判断是否有按键 + await driver.assertComponentExist(ON.text('Draw Star')); + let drawStarBtn = await driver.findComponent(ON.text('Draw Star')); + // 点击'Draw Star'按钮 + await drawStarBtn.click(); + await driver.delayMs(1000); + // 判断drawPattern方法已执行 + await driver.assertComponentExist(ON.text('draw star')); + + // 判断是否有XComponent组件 + let xcomponent = await driver.findComponent(ON.id('ndkxcomponent')); + // 点击XComponent组件 + await xcomponent.click(); + await driver.delayMs(1000); + // 判断touch回调已执行 + await driver.assertComponentExist(ON.text('change color')); + console.info(TAG, 'DrawShape_001 end'); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/testability/TestAbility.ets b/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/testability/TestAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..5c0bdcdd07892b4af702bfe2855869f5afcfc3f1 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/testability/TestAbility.ets @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import UIAbility from '@ohos.app.ability.UIAbility'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import hilog from '@ohos.hilog'; +import { Hypium } from '@ohos/hypium'; +import testsuite from '../test/List.test'; +import window from '@ohos.window'; +import Want from '@ohos.app.ability.Want'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; + +export default class TestAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam){ + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate'); + hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); + hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? ''); + let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs = AbilityDelegatorRegistry.getArguments(); + hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!'); + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + onDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage : window.WindowStage) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate'); + windowStage.loadContent('testability/pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/testability/pages/Index.ets b/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/testability/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..e1281d11efc7780af10fc8cb11917d45447a4a9a --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import hilog from '@ohos.hilog'; + +@Entry +@Component +struct Index { + aboutToAppear(){ + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear'); + } + @State message: string = 'Hello World'; + build(){ + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + } + .type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(() => { + }) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/ohosTest/module.json5 b/ArkUIKit/NdkXComponent/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a7685a59ea27672ae8074c984c4699bd73f36a5b --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/ohosTest/module.json5 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntry": "./ets/testability/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "exported": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/ArkUIKit/NdkXComponent/entry/src/ohosTest/resources/base/element/color.json b/ArkUIKit/NdkXComponent/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/ohosTest/resources/base/element/string.json b/ArkUIKit/NdkXComponent/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..65d8fa5a7cf54aa3943dcd0214f58d1771bc1f6c --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/entry/src/ohosTest/resources/base/media/icon.png b/ArkUIKit/NdkXComponent/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/ArkUIKit/NdkXComponent/entry/src/ohosTest/resources/base/media/icon.png differ diff --git a/ArkUIKit/NdkXComponent/entry/src/ohosTest/resources/base/profile/test_pages.json b/ArkUIKit/NdkXComponent/entry/src/ohosTest/resources/base/profile/test_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..b7e7343cacb32ce982a45e76daad86e435e054fe --- /dev/null +++ b/ArkUIKit/NdkXComponent/entry/src/ohosTest/resources/base/profile/test_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "testability/pages/Index" + ] +} diff --git a/ArkUIKit/NdkXComponent/hvigor/hvigor-config.json5 b/ArkUIKit/NdkXComponent/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..f70ecd4112d94f9aa555adf898d53f18bf58f3e9 --- /dev/null +++ b/ArkUIKit/NdkXComponent/hvigor/hvigor-config.json5 @@ -0,0 +1,5 @@ +{ + "modelVersion": "5.0.0", + "dependencies": { + } +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/hvigorfile.ts b/ArkUIKit/NdkXComponent/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..6478186902c0c1ad7c966a929c7d6b7d8ae7a9f3 --- /dev/null +++ b/ArkUIKit/NdkXComponent/hvigorfile.ts @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +export { appTasks } from '@ohos/hvigor-ohos-plugin'; \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/oh-package.json5 b/ArkUIKit/NdkXComponent/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..1dfe27c7da2c2f6b41bef993a3688bf5fbcb4d4a --- /dev/null +++ b/ArkUIKit/NdkXComponent/oh-package.json5 @@ -0,0 +1,13 @@ +{ + "modelVersion": "5.0.0", + "license": "", + "devDependencies": { + "@ohos/hypium": "1.0.6" + }, + "author": "", + "name": "ndkxcomponent", + "description": "Please describe the basic information.", + "main": "", + "version": "1.0.0", + "dependencies": {} +} \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/ohosTest.md b/ArkUIKit/NdkXComponent/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..5469eacbec87545aec4cfaa42c141af8859124e1 --- /dev/null +++ b/ArkUIKit/NdkXComponent/ohosTest.md @@ -0,0 +1,9 @@ +# NdkXComponent 测试用例归档 + +## 用例表 + +|测试功能|预置条件|输入|预期输出|是否自动|测试结果| +|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------| +| 拉起应用 | 设备正常运行 | |成功拉起应用|是| Pass | +| 绘制图形 | 位于首页 | 1、点击**Draw Star** | 1、页面显示出一个五角星 | 是 | Pass | +| 响应触摸事件 | 位于首页,且已经显示了五角星 | 1、点击XComponent区域(灰色背景部分) | 1、页面中的五角星改变颜色 | 是 | Pass | \ No newline at end of file diff --git a/ArkUIKit/NdkXComponent/screenshots/device/changeColor.png b/ArkUIKit/NdkXComponent/screenshots/device/changeColor.png new file mode 100644 index 0000000000000000000000000000000000000000..07586fceb2d038482dd984b921a7c80871824bb8 Binary files /dev/null and b/ArkUIKit/NdkXComponent/screenshots/device/changeColor.png differ diff --git a/ArkUIKit/NdkXComponent/screenshots/device/drawStar.png b/ArkUIKit/NdkXComponent/screenshots/device/drawStar.png new file mode 100644 index 0000000000000000000000000000000000000000..e8be339ee8a16dae2c1ce350747f8e1f09782692 Binary files /dev/null and b/ArkUIKit/NdkXComponent/screenshots/device/drawStar.png differ diff --git a/ArkUIKit/NdkXComponent/screenshots/device/main.png b/ArkUIKit/NdkXComponent/screenshots/device/main.png new file mode 100644 index 0000000000000000000000000000000000000000..a51df8c9cf759098882721219d5c9f4b5acfb0c8 Binary files /dev/null and b/ArkUIKit/NdkXComponent/screenshots/device/main.png differ