diff --git a/ArkUIKit/AccessibilityCapi/.gitignore b/ArkUIKit/AccessibilityCapi/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/AppScope/app.json5 b/ArkUIKit/AccessibilityCapi/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..78af2cd4745fcc6792f8d46ceeb9ae8f6a761309 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "com.example.accessibilityCapi", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/ArkUIKit/AccessibilityCapi/AppScope/resources/base/element/string.json b/ArkUIKit/AccessibilityCapi/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..8829529342444f211e7fd0428202be9feb85b8b7 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "accessibilityCapi" + } + ] +} diff --git a/ArkUIKit/AccessibilityCapi/AppScope/resources/base/media/background.png b/ArkUIKit/AccessibilityCapi/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/AccessibilityCapi/AppScope/resources/base/media/background.png differ diff --git a/ArkUIKit/AccessibilityCapi/AppScope/resources/base/media/foreground.png b/ArkUIKit/AccessibilityCapi/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/ArkUIKit/AccessibilityCapi/AppScope/resources/base/media/foreground.png differ diff --git a/ArkUIKit/AccessibilityCapi/AppScope/resources/base/media/layered_image.json b/ArkUIKit/AccessibilityCapi/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/build-profile.json5 b/ArkUIKit/AccessibilityCapi/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d7eca852872416dc5b03d25954e81a38473bdecf --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/build-profile.json5 @@ -0,0 +1,42 @@ +{ + "app": { + "products": [ + { + "name": "default", + "signingConfig": "default", + "targetSdkVersion": "6.0.0(20)", + "compatibleSdkVersion": "6.0.0(20)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "nativeCompiler": "BiSheng", + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/code-linter.json5 b/ArkUIKit/AccessibilityCapi/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..073990fa45394e1f8e85d85418ee60a8953f9b99 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/code-linter.json5 @@ -0,0 +1,32 @@ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/.gitignore b/ArkUIKit/AccessibilityCapi/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/build-profile.json5 b/ArkUIKit/AccessibilityCapi/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a198928aa7296e4850f8831ed633f3c58128471a --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/build-profile.json5 @@ -0,0 +1,44 @@ +{ + "apiType": "stageMode", + "buildOption": { + "resOptions": { + "copyCodeResource": { + "enable": false + } + }, + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + }, + "nativeLib": { + "debugSymbol": { + "strip": true, + "exclude": [] + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/hvigorfile.ts b/ArkUIKit/AccessibilityCapi/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..b0e3a1ab98a91bc918d6404b2413111a5011f14a --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/obfuscation-rules.txt b/ArkUIKit/AccessibilityCapi/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/oh-package-lock.json5 b/ArkUIKit/AccessibilityCapi/entry/oh-package-lock.json5 new file mode 100644 index 0000000000000000000000000000000000000000..877ad766072e5431e4d4353c806b56becbb94377 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/oh-package-lock.json5 @@ -0,0 +1,10 @@ +{ + "meta": { + "stableOrder": true, + "enableUnifiedLockfile": false + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": {}, + "packages": {} +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/oh-package.json5 b/ArkUIKit/AccessibilityCapi/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..dd7e99f8be3d707b9d7843289ccd013f7b87da19 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/oh-package.json5 @@ -0,0 +1,10 @@ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + } +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/CMakeLists.txt b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6c330c428c0216c2464d92ec442aceb9cd6c280c --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,51 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.5.0) +project(accessibilityCapi) + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +if(DEFINED PACKAGE_FIND_FILE) + include(${PACKAGE_FIND_FILE}) +endif() + +include_directories(${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/include) + +add_library(nativerender SHARED + manager/plugin_manager.cpp + manager/xcomponent_manager.cpp + manager/AccessibilityManager.cpp + napi_init.cpp + fakenode/fake_node.h + fakenode/fake_node.cpp) + +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( + libnative_window + + native_window +) + +target_link_libraries(nativerender PUBLIC ${hilog-lib} ${libace-lib} ${libnapi-lib} ${libnative_window}) \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/common/common.h b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/common/common.h new file mode 100644 index 0000000000000000000000000000000000000000..b7c7de958fc485190882f0e13e206008ddda12ab --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/common/common.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 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 +#include +#include +#include +/** + * Log print domain. + */ +const unsigned int LOG_PRINT_DOMAIN = 0xFF00; + + +#endif // NATIVE_XCOMPONENT_COMMON_H diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/common/timer.h b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/common/timer.h new file mode 100644 index 0000000000000000000000000000000000000000..fffbce6dbc643a9003093edccd7b83f0c58df79c --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/common/timer.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 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_TIMER_H +#define NATIVE_XCOMPONENT_TIMER_H + +#include +#include +#include +#include +#include +#include + +class Timer { +public: + Timer() : is_running(false) + {} + + void start(std::chrono::milliseconds total_duration, std::chrono::milliseconds interval, std::function task) + { + stop(); // 确保之前的计时器停止 + is_running = true; + timer_future = std::async(std::launch::async, [=]() { + auto start_time = std::chrono::steady_clock::now(); + auto end_time = start_time + total_duration; + auto next_check = start_time; + + while (is_running.load() && std::chrono::steady_clock::now() < end_time) { + std::this_thread::sleep_until(next_check); + next_check += interval; + if (is_running.load()) { + task(); + } + } + is_running = false; // 确保在结束时将 is_running 设置为 false + }); + } + + void stop() + { + is_running = false; + if (timer_future.valid()) { + timer_future.wait(); + } + } + + ~Timer() + { + stop(); + } + +private: + std::atomic is_running; + std::future timer_future; +}; + +#endif // NATIVE_XCOMPONENT_TIMER_H diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/fakenode/fake_node.cpp b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/fakenode/fake_node.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b65e3c7456244e3b2f2647e1a4c9773c99b7186b --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/fakenode/fake_node.cpp @@ -0,0 +1,164 @@ +// +// Created on 30/9/2025. +// +// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, +// please include "napi/native_api.h". +#include +#include "fake_node.h" + +void AccessibleObject::fillAccessibilityElement(ArkUI_AccessibilityElementInfo *element) { + if (!accessibilityText_.empty()) { + OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(element, accessibilityText_.data()); + } + if (!accessibilityDescription_.empty()) { + OH_ArkUI_AccessibilityElementInfoSetAccessibilityDescription(element, accessibilityDescription_.data()); + } + OH_ArkUI_AccessibilityElementInfoSetComponentType(element, ObjectType()); + OH_ArkUI_AccessibilityElementInfoSetContents(element, Name().data()); + OH_ArkUI_AccessibilityElementInfoSetHintText(element, Hint()); + OH_ArkUI_AccessibilityElementInfoSetVisible(element, IsVisible()); + OH_ArkUI_AccessibilityElementInfoSetEnabled(element, IsEnable()); + OH_ArkUI_AccessibilityElementInfoSetClickable(element, Clickable()); + OH_ArkUI_AccessibilityElementInfoSetFocusable(element, Focusable()); + OH_ArkUI_AccessibilityElementInfoSetFocused(element, Focused()); + OH_ArkUI_AccessibilityElementInfoSetIsPassword(element, isPassword_); + OH_ArkUI_AccessibilityElementInfoSetScrollable(element, isScrollable_); + OH_ArkUI_AccessibilityElementInfoSetLongClickable(element, isLongClick_); + OH_ArkUI_AccessibilityElementInfoSetEditable(element, true); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(element, isGroup_); + OH_ArkUI_AccessibilityElementInfoSetCheckable(element, checkable_); + OH_ArkUI_AccessibilityElementInfoSetChecked(element, checked_); + OH_ArkUI_AccessibilityElementInfoSetSelected(element, checkable_); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(element, accessibilityLevel_.data()); + if (ObjectType() == "FakeSilder") { + OH_ArkUI_AccessibilityElementInfoSetRangeInfo(element, &rangeInfo_); + } + if (ObjectType() == "FakeList") { + OH_ArkUI_AccessibilityElementInfoSetGridInfo(element, &gridInfo_); + } + if (ObjectType() == "FakeSwiper") { + OH_ArkUI_AccessibilityElementInfoSetGridItemInfo(element, &gridItemInfo_); + } + if (selectedTextStart_ < selectedTextEnd_) { + if (0 <= selectedTextStart_ <= accessibilityText_.size()) { + OH_ArkUI_AccessibilityElementInfoSetSelectedTextStart(element, selectedTextStart_); + } + if (0 <= selectedTextEnd_ <= accessibilityText_.size()) { + OH_ArkUI_AccessibilityElementInfoSetSelectedTextEnd(element, selectedTextEnd_); + } + } + if (itemCount_ >= endItemIndex_ >0 && startItemIndex_ <= currentItemIndex_ <= endItemIndex_) { + OH_ArkUI_AccessibilityElementInfoSetItemCount(element, itemCount_); + OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(element, startItemIndex_); + OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex(element, currentItemIndex_); + OH_ArkUI_AccessibilityElementInfoSetEndItemIndex(element, endItemIndex_); + } + OH_ArkUI_AccessibilityElementInfoSetAccessibilityOffset(element, offset_); + OH_ArkUI_AccessibilityElementInfoSetZIndex(element, zIndex_); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityOpacity(element, opacity_); + OH_ArkUI_AccessibilityElementInfoSetBackgroundImage(element, backgroundImage_.data()); + OH_ArkUI_AccessibilityElementInfoSetBackgroundColor(element, backgroundColor_.data()); + OH_ArkUI_AccessibilityElementInfoSetBlur(element, blue_.data()); + OH_ArkUI_AccessibilityElementInfoSetHitTestBehavior(element, HitTestBehavior_.data()); + + ArkUI_AccessibleAction actions[10]; + int index = 0; + if (this->Clickable()) { + actions[index].actionType = ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; + actions[index].description = "Click"; + index++; + } + + if (this->Focusable()) { + actions[index].actionType = ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; + actions[index].description = "Focus"; + index++; + actions[index].actionType = ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; + actions[index].description = "ClearFocus"; + index++; + } + if (index > 0) { + OH_ArkUI_AccessibilityElementInfoSetOperationActions(element, index, actions); + } +} + +void FakeWidget::AddButton(bool fillText, bool fillDescription) { + static int i = 1; + auto node = new FakeButton("button" + std::to_string(i)); + if (fillText) { + node->SetAccessibilityText("this is Text for button."); + } + if (fillDescription) { + node->SetAccessibilityDescription("this is Description for button."); + } + objects.push_back(node); + i++; +} + +void FakeWidget::AddText(bool fillText, bool fillDescription) { + static int i = 1; + auto node = new FakeText("text" + std::to_string(i)); + if (fillText) { + node->SetAccessibilityText("this is Text for text."); + } + if (fillDescription) { + node->SetAccessibilityDescription("this is Description for text."); + } + objects.push_back(node); + i++; +} + +void FakeWidget::AddSlider(bool fillText, bool fillDescription) { + static int i = 1; + auto node = new FakeSlider("slider" + std::to_string(i)); + ArkUI_AccessibleRangeInfo rangeInfo; + rangeInfo.current = 20; + rangeInfo.min = 0; + rangeInfo.max = 100; + node->SetRangeInfo(rangeInfo); + if (fillText) { + node->SetAccessibilityText("this is Text for slider."); + } + if (fillDescription) { + node->SetAccessibilityDescription("this is Description for slider."); + } + objects.push_back(node); + i++; +} +void FakeWidget::AddList(bool fillText, bool fillDescription) { + static int i = 1; + auto node = new FakeList("list" + std::to_string(i)); + ArkUI_AccessibleGridInfo gridInfo; + gridInfo.columnCount = 5; + gridInfo.rowCount = 5; + gridInfo.selectionMode = 0; + node->SetGridInfo(gridInfo); + if (fillText) { + node->SetAccessibilityText("this is Text for list."); + } + if (fillDescription) { + node->SetAccessibilityDescription("this is Description for list."); + } + objects.push_back(node); + i++; +} +void FakeWidget::AddSwiper(bool fillText, bool fillDescription) { + static int i = 1; + auto node = new FakeSwiper("swiper" + std::to_string(i)); + ArkUI_AccessibleGridItemInfo gridItemInfo; + gridItemInfo.rowSpan = 2; + gridItemInfo.rowIndex = 5; + gridItemInfo.columnSpan = 2; + gridItemInfo.columnIndex = 5; + gridItemInfo.selected = true; + gridItemInfo.heading = true; + node->SetGridItemInfo(gridItemInfo); + if (fillText) { + node->SetAccessibilityText("this is Text for list."); + } + if (fillDescription) { + node->SetAccessibilityDescription("this is Description for list."); + } + objects.push_back(node); + i++; +} diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/fakenode/fake_node.h b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/fakenode/fake_node.h new file mode 100644 index 0000000000000000000000000000000000000000..a349001e76ae9f141aad7ea063fd438bc376d88a --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/fakenode/fake_node.h @@ -0,0 +1,244 @@ +// +// Created on 30/9/2025. +// +// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, +// please include "napi/native_api.h". + +#ifndef ACCESSIBILITY_CAPI_FAKE_NODE_H +#define ACCESSIBILITY_CAPI_FAKE_NODE_H +#include +#include +#include +#include "common/common.h" +#include + +class AccessibleObject { +public: + AccessibleObject(const std::string &name) : name_(name), originName_(name) {} +// 设置string和int类型属性 + void SetAccessibilityLevel(const std::string &accessibilityLevel) { accessibilityLevel_ = accessibilityLevel; } + void SetAccessibilityText(const std::string &accessibilityText) { + accessibilityText_ = accessibilityText; + } + void SetAccessibilityDescription(const std::string &accessibilityDescription) { + accessibilityDescription_ = accessibilityDescription; + } + void SetAnnouncedForAccessibility(const std::string &AnnouncedForAccessibility) { + announcedForAccessibility_ = AnnouncedForAccessibility; + } + const std::string getAnnouncedForAccessibility() { return announcedForAccessibility_;} + void SetName(const std::string &name) { name_ = name; } + std::string Name() const { return name_; } + std::string OriginName() const { return originName_; } + + void SetBackgroundColor(const std::string &color) { + backgroundColor_ = color; + } + void SetBackgroundImage(const std::string &image) { + backgroundImage_ = image; + } + void SetBlue(const std::string &blue) { + blue_ = blue; + } + void SetHitTestBehavior(const std::string &hitTestBehavior) { + HitTestBehavior_ = hitTestBehavior; + } + void SetSelectedText(int32_t textStart, int32_t textEnd) { + selectedTextStart_ = textStart; + selectedTextEnd_ = textEnd; + } + void SetSelectedItem(int32_t itemCount, int32_t itemStart, int32_t itemCurrent, int32_t itemEnd) { + itemCount_ = itemCount; + startItemIndex_ = itemStart; + endItemIndex_ = itemEnd; + currentItemIndex_ = itemCurrent; + } + void SetOffset(int32_t offset) { offset_ = offset; } + void SetRangeInfo(ArkUI_AccessibleRangeInfo rangeInfo) { rangeInfo_ = rangeInfo; } + ArkUI_AccessibleRangeInfo GetRangeInfo() {return rangeInfo_;} + ArkUI_AccessibleGridInfo GetGridInfo() {return gridInfo_;} + ArkUI_AccessibleGridItemInfo GetGridItemInfo() {return gridItemInfo_;} + void SetGridInfo(ArkUI_AccessibleGridInfo gridInfo) { gridInfo_ = gridInfo; } + void SetGridItemInfo(ArkUI_AccessibleGridItemInfo gridItemInfo) {gridItemInfo_ = gridItemInfo; } + + void SetFocus(bool focus) { focus_ = focus; } + virtual void SetFocusable(bool focusable) {focusable_ = focusable;} + virtual void SetClickable(bool clickable) { clickable_ = clickable; } + void SetChecked(bool checked) { checked_ = checked; } + void SetCheckable(bool checkable) { checkable_ = checkable; } + void SetIsPassword(bool isPassword) { isPassword_ = isPassword; } + void SetScrollable(bool isScrollable) { isScrollable_ = isScrollable; } + void SetLongClickable(bool isLongClick) { isLongClick_ = isLongClick; } + void SetIsGroup(bool isGroup) { isGroup_ = isGroup; } + void SetIsSelected(bool isSelected) { isSelected_ = isSelected; } + void SetIsEnable(bool isEnable) { isEnable_ = isEnable; } + + virtual bool Focused() const { return focus_; } + virtual bool Focusable() const { return focusable_; } + + virtual const char *ObjectType() const { return "object"; } + virtual const char *Hint() const { return "It's object"; } + + virtual void onClick() {} + bool Clickable() const { return clickable_; } + bool IsVisible() const { return isVisible_; } + bool IsEnable() const { return isEnable_; } + void fillAccessibilityElement(ArkUI_AccessibilityElementInfo *element); + +private: + std::string accessibilityLevel_ = "auto"; + std::string accessibilityText_; + std::string accessibilityDescription_; + std::string announcedForAccessibility_; + std::string name_; + std::string originName_; + std::string backgroundColor_; + std::string backgroundImage_; + std::string blue_; + std::string HitTestBehavior_; + + bool clickable_ = true; + bool focus_ = false; + bool focusable_ = true; + bool checked_ = false; + bool checkable_ = false; + bool isPassword_ = false; + bool isScrollable_ = false; + bool isLongClick_ = false; + bool isSelected_ = false; + bool isGroup_ = false; + bool isVisible_ = true; + bool isEnable_ = true; + + int32_t selectedTextStart_ = 0; + int32_t selectedTextEnd_ = 0; + int32_t currentItemIndex_ = 0; + int32_t startItemIndex_ = 0; + int32_t endItemIndex_ = 0; + int32_t itemCount_ = 0; + int32_t zIndex_ = 0; + int32_t offset_ = 0; + float opacity_ = 0.0f; + + ArkUI_AccessibleRangeInfo rangeInfo_; + ArkUI_AccessibleGridInfo gridInfo_; + ArkUI_AccessibleGridItemInfo gridItemInfo_; +}; + +class FakeButton : public AccessibleObject { +public: + FakeButton(const std::string &name) : AccessibleObject(name) {} + const char *Hint() const { return "It's a button"; } + virtual const char *ObjectType() const { return "QButton"; } + virtual void onClick() { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "AccessibleObject", "FakeButton onClick"); + } +}; + +class FakeText : public AccessibleObject { +public: + FakeText(const std::string &name) : AccessibleObject(name) {} + + const char *Hint() const { return "It's a text"; } + virtual const char *ObjectType() const { return "FakeText"; } + virtual void onClick() { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "AccessibleObject", "FakeText onClick"); + } +}; + +class FakeSlider : public AccessibleObject { +public: + FakeSlider(const std::string &name) : AccessibleObject(name) {} + + const char *Hint() const { return "It's a slider"; } + virtual const char *ObjectType() const { return "FakeSlider"; } + virtual void onClick() { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "AccessibleObject", "FakeSlider onClick"); + } +}; + +class FakeList : public AccessibleObject { +public: + FakeList(const std::string &name) : AccessibleObject(name) {} + + const char *Hint() const { return "It's a list"; } + virtual const char *ObjectType() const { return "FakeList"; } + virtual void onClick() { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "AccessibleObject", "FakeList onClick"); + } +}; + +class FakeSwiper : public AccessibleObject { +public: + FakeSwiper(const std::string &name) : AccessibleObject(name) {} + + const char *Hint() const { return "It's a swiper"; } + virtual const char *ObjectType() const { return "FakeSwiper"; } + virtual void onClick() { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "AccessibleObject", "FakeSwiper onClick"); + } +}; + +class FakeWidget : public AccessibleObject { +public: + static FakeWidget &instance() { + static FakeWidget w; + return w; + } + + const std::vector &getAllObjects(std::string instanceId) const { + for (int i = 0; i < objects.size(); i++) { + objects[i]->SetName(objects[i]->OriginName() + instanceId); + } + return objects; + } + + AccessibleObject *getChild(int elementId) const { + if (elementId <= 0) { + return nullptr; + } + if (elementId - 1 >= objects.size()) { + return nullptr; + } + return objects.at(elementId - 1); + } + + virtual bool Focusable() const { return false; } + virtual const char *Hint() const { return "It's a widget"; } + virtual const char *ObjectType() const { return "Widget"; } + virtual void onClick() { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "AccessibleObject", "FakeWidget onClick"); + } + +private: + FakeWidget() : AccessibleObject("fakeWidget") { + this->AddButton(true, false); + this->AddButton(true, true); + this->AddButton(false, false); + this->AddButton(false, true); + this->AddText(true, false); + this->AddText(true, true); + this->AddText(false, false); + this->AddText(false, true); + this->AddSlider(true, true); + this->AddList(true, true); + this->AddSwiper(true, true); + } + ~FakeWidget() { + for (auto &obj : objects) { + delete obj; + } + } + +private: + void AddButton(bool fillText, bool fillDescription); + void AddText(bool fillText, bool fillDescription); + void AddSlider(bool fillText, bool fillDescription); + void AddList(bool fillText, bool fillDescription); + void AddSwiper(bool fillText, bool fillDescription); + +private: + std::vector objects; +}; + +#endif //ACCESSIBILITY_CAPI_FAKE_NODE_H diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/AccessibilityManager.cpp b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/AccessibilityManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..008288c1d5588addb9069b852a57ed99178481bf --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/AccessibilityManager.cpp @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2025 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 "fakenode/fake_node.h" +#include "AccessibilityManager.h" +#include +#include +const char *DEFAULT_ID = "XComponentIdSingle"; + +const char *LOG_PRINT_TEXT = "AccessibilityManager"; +namespace NativeXComponentSample { +void FillEvent(ArkUI_AccessibilityEventInfo *eventInfo, ArkUI_AccessibilityElementInfo *elementInfo, + ArkUI_AccessibilityEventType eventType, std::string announcedText) { + if (eventInfo == nullptr) { + return; + } + if (elementInfo == nullptr) { + return; + } + OH_ArkUI_AccessibilityEventSetEventType(eventInfo, eventType); + + OH_ArkUI_AccessibilityEventSetElementInfo(eventInfo, elementInfo); + + if (eventType == ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ANNOUNCE_FOR_ACCESSIBILITY && announcedText.size() > 0) { + OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility(eventInfo, announcedText.data()); + } +} + + +ArkUI_AccessibilityProvider *g_provider = nullptr; + +void AccessibilityManager::SendAccessibilityAsyncEvent(ArkUI_AccessibilityElementInfo *elementInfo, + ArkUI_AccessibilityEventType eventType, + std::string announcedText) { + + auto eventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); + + // 1.填写event内容 + FillEvent(eventInfo, elementInfo, eventType, announcedText); + // 2.callback + auto callback = [](int32_t errorCode) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, "result: %{public}d", errorCode); + }; + // 3. 调用接口发送事件给OH侧 + OH_ArkUI_SendAccessibilityAsyncEvent(g_provider, eventInfo, callback); +} + +AccessibilityManager::AccessibilityManager() { +// 多实例场景 + accessibilityProviderCallbacksWithInstance_.findAccessibilityNodeInfosById = FindAccessibilityNodeInfosById; + accessibilityProviderCallbacksWithInstance_.findAccessibilityNodeInfosByText = FindAccessibilityNodeInfosByText; + accessibilityProviderCallbacksWithInstance_.findFocusedAccessibilityNode = FindFocusedAccessibilityNode; + accessibilityProviderCallbacksWithInstance_.findNextFocusAccessibilityNode = FindNextFocusAccessibilityNode; + accessibilityProviderCallbacksWithInstance_.executeAccessibilityAction = ExecuteAccessibilityAction; + accessibilityProviderCallbacksWithInstance_.clearFocusedFocusAccessibilityNode = ClearFocusedFocusAccessibilityNode; + accessibilityProviderCallbacksWithInstance_.getAccessibilityNodeCursorPosition = GetAccessibilityNodeCursorPosition; +// 单实例场景 + accessibilityProviderCallbacks_.findAccessibilityNodeInfosById = FindAccessibilityNodeInfosById; + accessibilityProviderCallbacks_.findAccessibilityNodeInfosByText = FindAccessibilityNodeInfosByText; + accessibilityProviderCallbacks_.findFocusedAccessibilityNode = FindFocusedAccessibilityNode; + accessibilityProviderCallbacks_.findNextFocusAccessibilityNode = FindNextFocusAccessibilityNode; + accessibilityProviderCallbacks_.executeAccessibilityAction = ExecuteAccessibilityAction; + accessibilityProviderCallbacks_.clearFocusedFocusAccessibilityNode = ClearFocusedFocusAccessibilityNode; + accessibilityProviderCallbacks_.getAccessibilityNodeCursorPosition = GetAccessibilityNodeCursorPosition; +} + +void AccessibilityManager::Initialize(const std::string &id, OH_NativeXComponent *nativeXComponent) { + + int32_t ret = OH_NativeXComponent_GetNativeAccessibilityProvider(nativeXComponent, &provider); + + if (provider == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, "get provider is null"); + return; + } + + // 2.注册回调函数 +// ret = OH_ArkUI_AccessibilityProviderRegisterCallback(provider, &accessibilityProviderCallbacks_); + ret = OH_ArkUI_AccessibilityProviderRegisterCallbackWithInstance(id.c_str(), provider, &accessibilityProviderCallbacksWithInstance_); + if (ret != 0) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, + "InterfaceDesignTest OH_ArkUI_AccessibilityProviderRegisterCallback failed"); + return; + } + g_provider = provider; +} + +int32_t AccessibilityManager::FindAccessibilityNodeInfosById(const char* instanceId, int64_t elementId, ArkUI_AccessibilitySearchMode mode, + int32_t requestId, + ArkUI_AccessibilityElementInfoList *elementList) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, + "FindAccessibilityNodeInfosById start,instanceId %{public}s elementId: %{public}ld, requestId: %{public}d, mode: %{public}d",instanceId, + elementId, requestId, static_cast(mode)); + + if (elementList == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, + "FindAccessibilityNodeInfosById elementList is null"); + return OH_NATIVEXCOMPONENT_RESULT_FAILED; + } + int ret = 0; + const int parentOfRoot = -2100000; + if (elementId == -1) { + elementId = 0; + } + + if (mode == ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_RECURSIVE_CHILDREN) { + // arkUi框架设计的特殊值,根节点必须设置parentId为这个值 + + // fill some fake nodes + auto rootNode = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + assert(rootNode); + + OH_ArkUI_AccessibilityElementInfoSetElementId(rootNode, 0); + OH_ArkUI_AccessibilityElementInfoSetParentId(rootNode, parentOfRoot); + FakeWidget::instance().fillAccessibilityElement(rootNode); + + ArkUI_AccessibleRect rect; + rect.leftTopX = 0; + rect.leftTopY = 0; + rect.rightBottomX = 800; + rect.rightBottomY = 800; + ret = OH_ArkUI_AccessibilityElementInfoSetScreenRect(rootNode, &rect); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(rootNode, "no"); + auto objects = FakeWidget::instance().getAllObjects(instanceId); + int64_t childNodes[1024]; + for (int i = 0; i < objects.size(); i++) { + int elementId = i + 1; + + childNodes[i] = elementId; + } + for (int i = 0; i < objects.size(); i++) { + int elementId = i + 1; + + childNodes[i] = elementId; + auto child = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + OH_ArkUI_AccessibilityElementInfoSetElementId(child, elementId); + OH_ArkUI_AccessibilityElementInfoSetParentId(child, 0); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(child, "yes"); + objects[i]->fillAccessibilityElement(child); + + ArkUI_AccessibleRect rect; + rect.leftTopX = i * 100; + rect.leftTopY = 100; + rect.rightBottomX = i * 100 + 100; + rect.rightBottomY = 500; + OH_ArkUI_AccessibilityElementInfoSetScreenRect(child, &rect); + if (objects[i]->ObjectType() == "FakeSlider") { + auto rangeInfo = objects[i]->GetRangeInfo(); + OH_ArkUI_AccessibilityElementInfoSetRangeInfo(child, &rangeInfo); + } + if (objects[i]->ObjectType() == "FakeList") { + auto gridInfo = objects[i]->GetGridInfo(); + OH_ArkUI_AccessibilityElementInfoSetGridInfo(child, &gridInfo); + } + if (objects[i]->ObjectType() == "FakeSwiper") { + auto gridItemInfo = objects[i]->GetGridItemInfo(); + OH_ArkUI_AccessibilityElementInfoSetGridItemInfo(child, &gridItemInfo); + } + } + + ret = OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(rootNode, objects.size(), childNodes); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, + "FindAccessibilityNodeInfosById child count: %{public}ld %{public}d", + objects.size(), ret); + } else { + if (mode == ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { + auto &widget = FakeWidget::instance(); + AccessibleObject *obj = nullptr; + if (elementId == 0) { + obj = &widget; + } else { + obj = widget.getChild(elementId); + } + if (obj) { + auto node = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + OH_ArkUI_AccessibilityElementInfoSetElementId(node, elementId); + OH_ArkUI_AccessibilityElementInfoSetParentId(node, elementId == 0 ? parentOfRoot : 0); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(node, elementId == 0 ? "no" : "yes"); + obj->fillAccessibilityElement(node); + ArkUI_AccessibleRect rect; + if (elementId == 0) { + rect.leftTopX = 0; + rect.leftTopY = 0; + rect.rightBottomX = 800; + rect.rightBottomY = 800; + } else { + int i = elementId - 1; + rect.leftTopX = i * 100; + rect.leftTopY = 100; + rect.rightBottomX = i * 100 + 100; + rect.rightBottomY = 500; + } + + OH_ArkUI_AccessibilityElementInfoSetScreenRect(node, &rect); + if (elementId == 0) { + auto objects = FakeWidget::instance().getAllObjects(instanceId); + int64_t childNodes[1024]; + + for (int i = 0; i < objects.size(); i++) { + int elementId = i + 1; + + childNodes[i] = elementId; + auto child = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + OH_ArkUI_AccessibilityElementInfoSetElementId(child, elementId); + OH_ArkUI_AccessibilityElementInfoSetParentId(child, 0); + + objects[i]->fillAccessibilityElement(child); + + ArkUI_AccessibleRect rect; + rect.leftTopX = i * 100; + rect.leftTopY = 0; + rect.rightBottomX = i * 100 + 100; + rect.rightBottomY = 500; + OH_ArkUI_AccessibilityElementInfoSetScreenRect(child, &rect); + } + + ret = OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(node, objects.size(), childNodes); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, + "FindAccessibilityNodeInfosById child2 count: %{public}ld", + objects.size()); + } + } + } + } + + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, "FindAccessibilityNodeInfosById end"); + return OH_NATIVEXCOMPONENT_RESULT_SUCCESS; +} + +int32_t AccessibilityManager::FindAccessibilityNodeInfosByText(const char* instanceId, int64_t elementId, const char *text, int32_t requestId, + ArkUI_AccessibilityElementInfoList *elementList) { + return OH_NATIVEXCOMPONENT_RESULT_SUCCESS; +} + +int32_t AccessibilityManager::FindFocusedAccessibilityNode(const char* instanceId, int64_t elementId, ArkUI_AccessibilityFocusType focusType, + int32_t requestId, + ArkUI_AccessibilityElementInfo *elementInfo) + +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, + "FindFocusedAccessibilityNode elementId: %{public}ld, requestId: %{public}d, focusType: %{public}d", + elementId, requestId, static_cast(focusType)); + + // TODO + + + return OH_NATIVEXCOMPONENT_RESULT_SUCCESS; +} + +int32_t AccessibilityManager::FindNextFocusAccessibilityNode(const char* instanceId, int64_t elementId, + ArkUI_AccessibilityFocusMoveDirection direction, + int32_t requestId, + ArkUI_AccessibilityElementInfo *elementInfo) { + + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, + "FindNextFocusAccessibilityNode instanceId %{public}s elementId: %{public}ld, requestId: %{public}d, direction: %{public}d", + instanceId, elementId, requestId, static_cast(direction)); + + auto objects = FakeWidget::instance().getAllObjects(instanceId); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, + "objects.size() %{public}d",objects.size()); + // object.size 不包含 root节点 + if ((elementId < 0) || (elementId > objects.size())) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, + "1"); + return OH_NATIVEXCOMPONENT_RESULT_FAILED; + } + int64_t nextElementId = -1; + if (direction == ARKUI_ACCESSIBILITY_NATIVE_DIRECTION_FORWARD) { + nextElementId = elementId + 1; + } else { + nextElementId = elementId - 1; + } + + // 屏幕朗读约束 如果是根节点 然后backward的话需要回到最后一个节点 + if ((nextElementId == -1) && (direction == ARKUI_ACCESSIBILITY_NATIVE_DIRECTION_BACKWARD)) { + nextElementId = objects.size(); + } + + if (nextElementId > objects.size()) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, "2"); + return OH_NATIVEXCOMPONENT_RESULT_FAILED; + } + + if (nextElementId <= 0) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, "3"); + return OH_NATIVEXCOMPONENT_RESULT_FAILED; + } + + OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfo, nextElementId); + OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, 0); + + // id 比object索引大1 + objects[nextElementId - 1]->fillAccessibilityElement(elementInfo); + + ArkUI_AccessibleRect rect; + rect.leftTopX = nextElementId * 100; + rect.leftTopY = 0; + rect.rightBottomX = nextElementId * 100 + 100; + rect.rightBottomY = 500; + OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfo, &rect); + auto eventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); + OH_ArkUI_AccessibilityEventSetRequestFocusId(eventInfo, requestId); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, + "4 %{public}ld",nextElementId); + return OH_NATIVEXCOMPONENT_RESULT_SUCCESS; +} + +int32_t AccessibilityManager::ExecuteAccessibilityAction(const char* instanceId, int64_t elementId, ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments *actionArguments, + int32_t requestId) { + + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, + "ExecuteAccessibilityAction elementId: %{public}ld, action: %{public}d", elementId, action); + auto object = FakeWidget::instance().getChild(elementId); + + if (!object) + return 0; + auto announcedText = object->getAnnouncedForAccessibility(); + auto element = OH_ArkUI_CreateAccessibilityElementInfo(); + OH_ArkUI_AccessibilityElementInfoSetElementId(element, elementId); + const char *actionKey = "some_key"; + char *actionValue = NULL; + OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, actionKey, &actionValue); + switch (action) { + case ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: + if (object) { + object->onClick(); + object->fillAccessibilityElement(element); + } + AccessibilityManager::SendAccessibilityAsyncEvent(element, + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_CLICKED, announcedText); + break; + case ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: + if (object) { + object->SetFocus(true); + + object->fillAccessibilityElement(element); + } + + AccessibilityManager::SendAccessibilityAsyncEvent(element, + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED, + announcedText); + + break; + case ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: + if (object) { + object->SetFocus(false); + object->fillAccessibilityElement(element); + } + AccessibilityManager::SendAccessibilityAsyncEvent( + element, ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED, + announcedText); + break; + } + + OH_ArkUI_DestoryAccessibilityElementInfo(element); + return OH_NATIVEXCOMPONENT_RESULT_SUCCESS; +} + +int32_t AccessibilityManager::ClearFocusedFocusAccessibilityNode(const char* instanceId) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, "ClearFocusedFocusAccessibilityNode"); + return OH_NATIVEXCOMPONENT_RESULT_SUCCESS; +} + +int32_t AccessibilityManager::GetAccessibilityNodeCursorPosition(const char* instanceId, int64_t elementId, int32_t requestId, int32_t *index) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, "GetAccessibilityNodeCursorPosition"); + return OH_NATIVEXCOMPONENT_RESULT_SUCCESS; +} + +void AccessibilityManager::Initialize(OH_NativeXComponent *nativeXComponent) { + + int32_t ret = OH_NativeXComponent_GetNativeAccessibilityProvider(nativeXComponent, &provider); + + if (provider == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, "get provider is null"); + return; + } + + // 2.注册回调函数 + ret = OH_ArkUI_AccessibilityProviderRegisterCallback(provider, &accessibilityProviderCallbacks_); +// ret = OH_ArkUI_AccessibilityProviderRegisterCallbackWithInstance(id.c_str(), provider, &accessibilityProviderCallbacksWithInstance_); + if (ret != 0) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, + "InterfaceDesignTest OH_ArkUI_AccessibilityProviderRegisterCallback failed"); + return; + } + g_provider = provider; +} + +int32_t AccessibilityManager::FindAccessibilityNodeInfosById(int64_t elementId, ArkUI_AccessibilitySearchMode mode, + int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { + return FindAccessibilityNodeInfosById(DEFAULT_ID, elementId, mode, requestId, elementList); +} + +int32_t AccessibilityManager::FindAccessibilityNodeInfosByText(int64_t elementId, const char* text, int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList) { + return FindAccessibilityNodeInfosByText(DEFAULT_ID, elementId, text, requestId, elementList); +} + +int32_t AccessibilityManager::FindFocusedAccessibilityNode(int64_t elementId, ArkUI_AccessibilityFocusType focusType, + int32_t requestId, ArkUI_AccessibilityElementInfo* elementInfo) { + return FindFocusedAccessibilityNode(DEFAULT_ID, elementId, focusType, requestId, elementInfo); +} + +int32_t AccessibilityManager::FindNextFocusAccessibilityNode(int64_t elementId, ArkUI_AccessibilityFocusMoveDirection direction, + int32_t requestId, ArkUI_AccessibilityElementInfo* elementInfo) { + return FindNextFocusAccessibilityNode(DEFAULT_ID, elementId, direction, requestId, elementInfo); +} + +int32_t AccessibilityManager::ExecuteAccessibilityAction(int64_t elementId, ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments *actionArguments, int32_t requestId) { + return ExecuteAccessibilityAction(DEFAULT_ID, elementId, action, actionArguments, requestId); +} + +int32_t AccessibilityManager::ClearFocusedFocusAccessibilityNode() { + return ClearFocusedFocusAccessibilityNode(DEFAULT_ID); +} + +int32_t AccessibilityManager::GetAccessibilityNodeCursorPosition(int64_t elementId, int32_t requestId, int32_t* index) { + return GetAccessibilityNodeCursorPosition(DEFAULT_ID, elementId, requestId, index); +} +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/AccessibilityManager.h b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/AccessibilityManager.h new file mode 100644 index 0000000000000000000000000000000000000000..3369a321e1307ebd517bc1ace5c1287d29b99ea6 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/AccessibilityManager.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2025 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 OH_ACCESSIBILITYDEMO_ACCESSIBILITYMANAGER_H +#define OH_ACCESSIBILITYDEMO_ACCESSIBILITYMANAGER_H + +#include + +namespace NativeXComponentSample +{ + +class AccessibilityManager { +public: + AccessibilityManager(); + void Initialize(const std::string &id, OH_NativeXComponent* nativeXComponent); + void Initialize(OH_NativeXComponent* nativeXComponent); + +public: +// 多实例场景 + static int32_t FindAccessibilityNodeInfosById(const char* instanceId, int64_t elementId, ArkUI_AccessibilitySearchMode mode, + int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList); + + static int32_t FindAccessibilityNodeInfosByText(const char* instanceId, int64_t elementId, const char* text, int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList); + + static int32_t FindFocusedAccessibilityNode(const char* instanceId, int64_t elementId, ArkUI_AccessibilityFocusType focusType, + int32_t requestId, ArkUI_AccessibilityElementInfo* elementInfo); + + static int32_t FindNextFocusAccessibilityNode(const char* instanceId, int64_t elementId, ArkUI_AccessibilityFocusMoveDirection direction, + int32_t requestId, ArkUI_AccessibilityElementInfo* elementInfo); + + static int32_t ExecuteAccessibilityAction(const char* instanceId, int64_t elementId, ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments *actionArguments, int32_t requestId); + + static int32_t ClearFocusedFocusAccessibilityNode(const char* instanceId); + + static int32_t GetAccessibilityNodeCursorPosition(const char* instanceId, int64_t elementId, int32_t requestId, int32_t* index); +// 单实例场景 + static int32_t FindAccessibilityNodeInfosById(int64_t elementId, ArkUI_AccessibilitySearchMode mode, + int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList); + + static int32_t FindAccessibilityNodeInfosByText(int64_t elementId, const char* text, int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList); + + static int32_t FindFocusedAccessibilityNode(int64_t elementId, ArkUI_AccessibilityFocusType focusType, + int32_t requestId, ArkUI_AccessibilityElementInfo* elementInfo); + + static int32_t FindNextFocusAccessibilityNode(int64_t elementId, ArkUI_AccessibilityFocusMoveDirection direction, + int32_t requestId, ArkUI_AccessibilityElementInfo* elementInfo); + + static int32_t ExecuteAccessibilityAction(int64_t elementId, ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments *actionArguments, int32_t requestId); + + static int32_t ClearFocusedFocusAccessibilityNode(); + + static int32_t GetAccessibilityNodeCursorPosition(int64_t elementId, int32_t requestId, int32_t* index); + +private: + static void SendAccessibilityAsyncEvent(ArkUI_AccessibilityElementInfo *elementInfo, + ArkUI_AccessibilityEventType eventType, std::string announcedText); +private: + ArkUI_AccessibilityProvider* provider = nullptr; + ArkUI_AccessibilityProviderCallbacks accessibilityProviderCallbacks_; + ArkUI_AccessibilityProviderCallbacksWithInstance accessibilityProviderCallbacksWithInstance_; +}; +} +#endif //OH_ACCESSIBILITYDEMO_ACCESSIBILITYMANAGER_H diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/plugin_manager.cpp b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/plugin_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a5729f851eb71ec4e2235234f116265ca62de54 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/plugin_manager.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2023 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 +// native render +#include +#include +#include + +#include "common/common.h" + +#include "xcomponent_manager.h" + +using namespace std; + +namespace NativeXComponentSample { +PluginManager PluginManager::pluginManager_; +AbilityInfo PluginManager::m_abilityInfo; + +const char *LOG_TAG_RECT = "TestRect"; + +napi_status callMethod(napi_env env, napi_value obj, const std::string &methodName, napi_value *out) +{ + napi_value func = nullptr; + napi_status ret = napi_ok; + + ret = napi_get_named_property(env, obj, methodName.data(), &func); + if (ret != napi_ok) + return ret; + + ret = napi_call_function(env, obj, func, 0, nullptr, out); + + return ret; +} + +void AbilityInfo::Init(napi_env env, napi_value uiAbility, napi_value windowStage) +{ + napi_value ohosWindow; + napi_status code = callMethod(env, windowStage, "getMainWindowSync", &ohosWindow); + if (code != napi_ok) { + napi_throw_error(env, nullptr, "call getMainWindowSync failed"); + } + this->env = env; + + napi_create_reference(env, uiAbility, 1, &this->uiAbility); + napi_create_reference(env, windowStage, 1, &this->windowStage); + napi_create_reference(env, ohosWindow, 1, &this->window); +} + +napi_value AbilityInfo::getWindow() +{ + napi_value value; + if (this->window) { + napi_status status = napi_get_reference_value(env, window, &value); + if (status != napi_ok) { + napi_throw_type_error(env, NULL, "getWindow failed"); + } + } + return value; +} + +AbilityInfo::~AbilityInfo() +{ + // todo release ref +} + + + +void setupNativeWindowBufferUsage(::OHNativeWindow *nativeWindow, std::uint64_t usageSetBits) +{ + std::uint64_t windowBufferUsage = 0; + auto getUsageRes = + ::OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, ::NativeWindowOperation::GET_USAGE, &windowBufferUsage); + + std::uint64_t requestedWindowBufferUsage = windowBufferUsage | usageSetBits; + if (requestedWindowBufferUsage != windowBufferUsage) { + auto setUsageRes = ::OH_NativeWindow_NativeWindowHandleOpt( + nativeWindow, ::NativeWindowOperation::SET_USAGE, requestedWindowBufferUsage); + } +} + +PluginManager::PluginManager() + :xcomponentMgr(new XComponentManager) +{ +} + +PluginManager::~PluginManager() +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "~PluginManager"); + delete xcomponentMgr; +} + +void PluginManager::AttachXComponent(const std::string &id, + OH_NativeXComponent *nativeXComponent, OHNativeWindow *window) +{ + this->xcomponentMgr->SetNativeXComponent(id, nativeXComponent, window); +} + +void PluginManager::Export(napi_env env, napi_value exports) +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "Export: start execute"); + if ((env == nullptr) || (exports == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "Export: env or exports is null"); + return; + } + + napi_value exportInstance = nullptr; + if (napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "Export: napi_get_named_property fail"); + return; + } + + OH_NativeXComponent *nativeXComponent = nullptr; + if (napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent)) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "Export: napi_unwrap fail"); + return; + } + + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print( + LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "Export: OH_NativeXComponent_GetXComponentId fail"); + return; + } + + this->xcomponentMgr->RegisterCallback(nativeXComponent); +} + +} // namespace NativeXComponentSample \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/plugin_manager.h b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/plugin_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..02b6174b40a831d45828e19d74953642f52a0c0f --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/plugin_manager.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 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 "xcomponent_manager.h" +namespace NativeXComponentSample { + +class AbilityInfo { +public: + napi_ref uiAbility; + napi_ref windowStage; + napi_ref window; + napi_env env; + void Init(napi_env env, napi_value uiAbility, napi_value windowStage); + napi_value getWindow(); + ~AbilityInfo(); +}; + +class PluginManager { +public: + PluginManager(); + ~PluginManager(); + + static PluginManager *GetInstance() + { + return &PluginManager::pluginManager_; + } + + static AbilityInfo &GetAbilityInfo() + { + return m_abilityInfo; + } + + + void AttachXComponent(const std::string &id, OH_NativeXComponent *nativeXComponent, OHNativeWindow *window); + + void Export(napi_env env, napi_value exports); + +private: + static PluginManager pluginManager_; + + static AbilityInfo m_abilityInfo; + XComponentManager *xcomponentMgr; +}; +} // namespace NativeXComponentSample +#endif // NATIVE_XCOMPONENT_PLUGIN_MANAGER_H diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/xcomponent_manager.cpp b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/xcomponent_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..27bf7ca610aa9f2a562cf0fd3e91bc442921fa77 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/xcomponent_manager.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2023 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 "common/common.h" +#include "xcomponent_manager.h" +#include +#include + +#include +#include + +#include "manager/AccessibilityManager.h" +#include "plugin_manager.h" + + +void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceCreatedCB"); + if ((component == nullptr) || (window == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", + "OnSurfaceCreatedCB: component or window is null"); + return; + } + + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", + "OnSurfaceCreatedCB: Unable to get XComponent id"); + return; + } + + std::string id(idStr); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceCreatedCB component id is %{public}s", id.c_str()); + + auto plugin = NativeXComponentSample::PluginManager::GetInstance(); + plugin->AttachXComponent(id, component, reinterpret_cast<::OHNativeWindow *>(window)); +} + +void OnSurfaceChangedCB(OH_NativeXComponent *component, void *window) {} + +void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window) {} + +void DispatchTouchEventCB(OH_NativeXComponent *component, void *window) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchTouchEventCB"); + OH_NativeXComponent_TouchEvent touchEvent; +} + +void DispatchHoverEvent(::OH_NativeXComponent *xComponent, bool isHover) {} + +namespace NativeXComponentSample { + +XComponentManager::XComponentManager() : accessibilityManager(new AccessibilityManager()) {} + +XComponentManager::~XComponentManager() { delete accessibilityManager; } + +void XComponentManager::RegisterCallback(OH_NativeXComponent *nativeXComponent) { + renderCallback_.OnSurfaceCreated = ::OnSurfaceCreatedCB; + renderCallback_.OnSurfaceChanged = ::OnSurfaceChangedCB; + renderCallback_.OnSurfaceDestroyed = ::OnSurfaceDestroyedCB; + renderCallback_.DispatchTouchEvent = ::DispatchTouchEventCB; + int ret = OH_NativeXComponent_RegisterCallback(nativeXComponent, &renderCallback_); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "XComponentManager", "RegisterCallback %{public}d", ret); +} + +void XComponentManager::SetNativeXComponent(const std::string &id, OH_NativeXComponent *nativeXComponent, + OHNativeWindow *window) { + if (nativeXComponent == nullptr) { + return; + } + auto it = nativeXComponentMap_.find(id); + if (id.c_str() == singleInstanceId) { + accessibilityManager->Initialize(nativeXComponent); + } else { + accessibilityManager->Initialize(id, nativeXComponent); + } + if (it != nativeXComponentMap_.end()) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "SetNativeXComponent", "%{public}s already exists", + id.data()); + return; + } else { + nativeXComponentMap_.emplace(id, XSurface{nativeXComponent, window}); + } + +} + +} // namespace NativeXComponentSample \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/xcomponent_manager.h b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/xcomponent_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..09f7039555d1404506c979da720f31d5d9946f3f --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/manager/xcomponent_manager.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 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_XCOMPONENT_MANAGER_H +#define NATIVE_XCOMPONENT_XCOMPONENT_MANAGER_H + +#include +#include +#include +#include +#include + +namespace NativeXComponentSample { + +class AccessibilityManager; +class XComponentManager { +public: + XComponentManager(); + ~XComponentManager(); + std::string singleInstanceId = "XComponentIdSingle"; + void RegisterCallback(OH_NativeXComponent *nativeXComponent); + + struct XSurface { + OH_NativeXComponent *xcomponent; + OHNativeWindow *window; + }; + +public: + + // manager xcomponent + void SetNativeXComponent(const std::string &id, OH_NativeXComponent *nativeXComponent, OHNativeWindow *window); + + XSurface GetXSurface(const std::string &id) const + { + auto it = nativeXComponentMap_.find(id); + return it != nativeXComponentMap_.end() ? it->second : XSurface{}; + } + +private: + std::unordered_map nativeXComponentMap_; + + OH_NativeXComponent_Callback renderCallback_; + OH_NativeXComponent_MouseEvent_Callback mouseCallback_; + AccessibilityManager *accessibilityManager; +}; +} // namespace NativeXComponentSample + +#endif // NATIVE_XCOMPONENT_XCOMPONENT_MANAGER_H \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/napi_init.cpp b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/napi_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..12b1f5c4188aaa00f3ed2c25d9d9972aa78756ea --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/napi_init.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 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; + } + + PluginManager::GetInstance()->Export(env, exports); + return exports; +} +EXTERN_C_END + +static napi_module nativerenderModule = { .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "nativerender", + .nm_priv = ((void*)0), + .reserved = { 0 } }; + +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&nativerenderModule); +} +} // namespace NativeXComponentSample diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/types/libnativerender/index.d.ts b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/types/libnativerender/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..a4ed17e3049d59cd0c6f37018b5c7b15e7ca8ffb --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/types/libnativerender/index.d.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 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 Window from '@ohos.window'; +import { type UIAbility } from '@kit.AbilityKit'; + diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/types/libnativerender/oh-package.json5 b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/types/libnativerender/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..78953253ec0ed6892ab6506b202a0b52579f6621 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/cpp/types/libnativerender/oh-package.json5 @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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. + */ + +{ + "name": "libnativerender.so", + "types": "./index.d.ts", + "version": "1.0", + "description": "Please describe the basic information." +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/ets/MyStage.ets b/ArkUIKit/AccessibilityCapi/entry/src/main/ets/MyStage.ets new file mode 100644 index 0000000000000000000000000000000000000000..4d588eca9e61fbd0332ae0ce7fe21bfbef026948 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/ets/MyStage.ets @@ -0,0 +1,17 @@ +import AbilityStage from '@ohos.app.ability.AbilityStage'; +import Want from '@ohos.app.ability.Want'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +export default class MyStage extends AbilityStage { + onCreate(): void { + + } + onNewProcessRequest(want: Want): string { + return ''; + } + onAcceptWant(want: Want): string { + let callerPidKey = 'ohos.aafwk.param.callerPid'; + hilog.info(0x0000, "testLaunch", "MyStage::onAcceptWant: callerPid: " + want.parameters![callerPidKey]); + return '0'; + } +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/ets/entryability/EntryAbility.ets b/ArkUIKit/AccessibilityCapi/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..c2a167e15569ba83ccdbf377346adb513d2742ca --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,48 @@ +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + } catch (err) { + hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); + } + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkUIKit/AccessibilityCapi/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..fae19f9dd53d2857e2843539cbedf5bee4a34b5a --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,16 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/ets/pages/Index.ets b/ArkUIKit/AccessibilityCapi/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..3bdbf433c7ca0f085e613af7c67a66f58001fdf6 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,77 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; +const msg_tag = '[accessibilityCapi]'; + +@Entry(undefined) +@Component +struct Index { + @LocalStorageLink('mainWindow') private mainWindow: window.Window | undefined = undefined; + @State isMultiInstance: boolean = false; + @State message: string = 'Hello World'; + @State msg_tag: string = 'accessibilityCapi'; + + build() { + Row() { + Column() { + Button('SubWindow').onClick(()=>{ + try { + this.mainWindow?.createSubWindowWithOptions('Modal', + {title: 'SubWindow', decorEnabled: true, isModal:true}) + } catch (err) { + console.error(`${msg_tag} code: ${err.code}, message: ${err.message}`); + } + }) + Button('XComponent单实例/多实例切换').onClick(()=>{ + this.isMultiInstance = !this.isMultiInstance; + console.info(`${msg_tag}: current XComponent multiInstance is ${this.isMultiInstance}`); + }) + if (this.isMultiInstance) { + XComponent({ + id: 'xComponentId1', + type: XComponentType.SURFACE, + libraryname: 'nativerender' + }) + .onDestroy(()=>{ + console.info(`${msg_tag} Destroy Sub Window`); + }) + .id('xComponentId1') + .focusable(true) + .background(Color.Green) + .width('100%') + .height('50%') + XComponent({ + id: 'xComponentId2', + type: XComponentType.SURFACE, + libraryname: 'nativerender' + }) + .onDestroy(()=>{ + console.info(`${msg_tag} Destroy Sub Window`); + }) + .id('xComponentId2') + .focusable(true) + .background(Color.Gray) + .width('100%') + .height('50%') + } else { + XComponent({ + id: 'xComponentIdSingle', + type: XComponentType.SURFACE, + libraryname: 'nativerender' + }) + .onDestroy(()=>{ + console.info(`${msg_tag} Destroy Sub Window`); + }) + .id('xComponentIdSingle') + .focusable(true) + .background(Color.Gray) + .width('100%') + .height('50%') + } + } + } + .width('100%') + .height('100%') + .focusable(true) + .defaultFocus(true) + } +} diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/module.json5 b/ArkUIKit/AccessibilityCapi/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..cb982452734c4cbde10f9d8eb53cf7f3d94097a8 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/module.json5 @@ -0,0 +1,51 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "srcEntry": "./ets/MyStage.ets", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "ohos.want.action.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/element/color.json b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..d66f9a7d4ac61fb8d215239ab3620b7bcd77bf33 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/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/AccessibilityCapi/entry/src/main/resources/base/element/float.json b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..5f0600c7083c3ac3776dcc13ce3e3f03c378fc6d --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/element/string.json b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/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/AccessibilityCapi/entry/src/main/resources/base/media/background.png b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/media/background.png differ diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/media/foreground.png b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/media/foreground.png differ diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/media/layered_image.json b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/media/startIcon.png b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/profile/backup_config.json b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..d742c2f96e7dd0f406f499941f3147345e998f95 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..55c3f007f87b7ce5206d325f968cc56f2f79441f --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/main/resources/dark/element/color.json b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..438d5bc43bb23c59c210d586b96635a72da5b64a --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/mock/Libentry.mock.ets b/ArkUIKit/AccessibilityCapi/entry/src/mock/Libentry.mock.ets new file mode 100644 index 0000000000000000000000000000000000000000..c2171716d040a605ef6af71e90b937a945f2677d --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/mock/Libentry.mock.ets @@ -0,0 +1,7 @@ +const NativeMock: Record = { + 'add': (a: number, b: number) => { + return a + b; + }, +}; + +export default NativeMock; \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/mock/mock-config.json5 b/ArkUIKit/AccessibilityCapi/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..6540976c9acc8afbd45895db6404334cff195465 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/mock/mock-config.json5 @@ -0,0 +1,5 @@ +{ + "libentry.so": { + "source": "src/mock/Libentry.mock.ets" + } +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/ohosTest/ets/test/Ability.test.ets b/ArkUIKit/AccessibilityCapi/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..85c78f67579d6e31b5f5aeea463e216b9b141048 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,35 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/ohosTest/ets/test/List.test.ets b/ArkUIKit/AccessibilityCapi/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..794c7dc4ed66bd98fa3865e07922906e2fcef545 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,5 @@ +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/ohosTest/module.json5 b/ArkUIKit/AccessibilityCapi/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..fb0d7837fd30b732c6a09b25ae2401679275291c --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/ohosTest/module.json5 @@ -0,0 +1,11 @@ +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ArkUIKit/AccessibilityCapi/entry/src/test/List.test.ets b/ArkUIKit/AccessibilityCapi/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..bb5b5c3731e283dd507c847560ee59bde477bbc7 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/test/List.test.ets @@ -0,0 +1,5 @@ +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/entry/src/test/LocalUnit.test.ets b/ArkUIKit/AccessibilityCapi/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..165fc1615ee8618b4cb6a622f144a9a707eee99f --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,33 @@ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/hvigor/hvigor-config.json5 b/ArkUIKit/AccessibilityCapi/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..bd35d296933eed3d5ced1a114a7be486cec8df93 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/hvigor/hvigor-config.json5 @@ -0,0 +1,23 @@ +{ + "modelVersion": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/ArkUIKit/AccessibilityCapi/hvigorfile.ts b/ArkUIKit/AccessibilityCapi/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..47113e2e36ecefde41c136272a0bd6ff745cffe4 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/oh-package-lock.json5 b/ArkUIKit/AccessibilityCapi/oh-package-lock.json5 new file mode 100644 index 0000000000000000000000000000000000000000..7c4feffd7338ba2ba9c9dc5cec5fb9f252c0c299 --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/oh-package-lock.json5 @@ -0,0 +1,28 @@ +{ + "meta": { + "stableOrder": true, + "enableUnifiedLockfile": false + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0", + "@ohos/hypium@1.0.24": "@ohos/hypium@1.0.24" + }, + "packages": { + "@ohos/hamock@1.0.0": { + "name": "", + "version": "1.0.0", + "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==", + "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hamock/-/hamock-1.0.0.har", + "registryType": "ohpm" + }, + "@ohos/hypium@1.0.24": { + "name": "", + "version": "1.0.24", + "integrity": "sha512-3dCqc+BAR5LqEGG2Vtzi8O3r7ci/3fYU+FWjwvUobbfko7DUnXGOccaror0yYuUhJfXzFK0aZNMGSnXaTwEnbw==", + "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.24.har", + "registryType": "ohpm" + } + } +} \ No newline at end of file diff --git a/ArkUIKit/AccessibilityCapi/oh-package.json5 b/ArkUIKit/AccessibilityCapi/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..1089e9b97ed0252fb4da9a5f896da3d1b9cac75b --- /dev/null +++ b/ArkUIKit/AccessibilityCapi/oh-package.json5 @@ -0,0 +1,10 @@ +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.24", + "@ohos/hamock": "1.0.0" + } +}