From f68c449009b850a206ba660162ca406259ce75dc Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 28 Aug 2024 15:46:47 +0800 Subject: [PATCH 001/151] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E6=97=A0=E9=9A=9C=E7=A2=8D=E6=9C=8D=E5=8A=A1=E7=9A=84?= =?UTF-8?q?ets=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../src/main/cpp/types/libflutter/index.d.ets | 7 +++ .../main/ets/embedding/engine/FlutterNapi.ets | 23 ++++++++ .../systemchannels/AccessibilityChannel.ets | 2 +- .../platform/AccessibilityEventsDelegate.ets | 2 +- .../platform/PlatformViewsController.ets | 4 +- .../src/main/ets/view/AccessibilityBridge.ets | 54 ++++++++++++++++++- 6 files changed, 87 insertions(+), 5 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets index bbaa2987bb..cf4729c183 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets @@ -17,6 +17,7 @@ import common from '@ohos.app.ability.common'; import resourceManager from '@ohos.resourceManager'; import image from '@ohos.multimedia.image'; import FlutterNapi from '../../../ets/embedding/engine/FlutterNapi'; +import { ByteBuffer } from '../../../ets/util/ByteBuffer'; export const getContext: (a: number) => napiContext; @@ -109,6 +110,12 @@ export const nativeXComponentDispatchMouseWheel: (nativeShellHolderId: number, timestamp: number ) => void; + +// send updateSemantics and updateCustomAccessibilityActions from ets to c++ +export const nativeUpdateSemantics: (buffer: ByteBuffer, strings: string[], stringAttributeArgs: ByteBuffer[]) => void; +export const nativeUpdateCustomAccessibilityActions: (buffer: ByteBuffer, strings: string[]) => void; + + /** * Detaches flutterNapi和engine之间的关联 * 这个方法执行前提是flutterNapi已经和engine关联 diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index 6fcf4a574f..88fe03d2a0 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -366,6 +366,29 @@ export default class FlutterNapi { } } + + // debug updateSemantics + updateSemantics(buffer: ByteBuffer, strings: string[], stringAttributeArgs: ByteBuffer[]): void { + this.ensureRunningOnMainThread(); + if(this.accessibilityDelegate != null) { + this.accessibilityDelegate.updateSemantics(buffer, strings, stringAttributeArgs); + } + // TODO(mattcarroll): log dropped messages when in debug mode + // (https://github.com/flutter/flutter/issues/25391) + Log.d(TAG, "updateSemantics is called"); + flutter.nativeUpdateSemantics(buffer, strings, stringAttributeArgs); + } + + updateCustomAccessibilityActions(buffer: ByteBuffer, strings: string[]): void { + this.ensureRunningOnMainThread(); + if(this.accessibilityDelegate != null) { + this.accessibilityDelegate.updateCustomAccessibilityActions(buffer, strings); + } + Log.d(TAG, "updateCustomAccessibilityActions is called"); + flutter.nativeUpdateCustomAccessibilityActions(buffer, strings); + } + + setLocalizationPlugin(localizationPlugin: LocalizationPlugin | null): void { this.localizationPlugin = localizationPlugin; } diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets index 9b2f9ee6cf..7246ee6213 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets @@ -112,7 +112,7 @@ export default class AccessibilityChannel implements MessageHandler{ } -interface AccessibilityMessageHandler extends AccessibilityDelegate { +export interface AccessibilityMessageHandler extends AccessibilityDelegate { announce(message: string): void; onTap(nodeId: number): void; onLongPress(nodeId: number): void; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/AccessibilityEventsDelegate.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/AccessibilityEventsDelegate.ets index ea9450d4aa..aae15ba935 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/AccessibilityEventsDelegate.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/AccessibilityEventsDelegate.ets @@ -32,7 +32,7 @@ export class AccessibilityEventsDelegate { return true; } - setAccessibilityBridge (accessibilityBridge: AccessibilityBridge): void { + setAccessibilityBridge (accessibilityBridge: AccessibilityBridge | null): void { this.accessibilityBridge = accessibilityBridge; } } \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/PlatformViewsController.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/PlatformViewsController.ets index 9b29731810..4ec7c08ed0 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/PlatformViewsController.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/PlatformViewsController.ets @@ -115,11 +115,11 @@ export default class PlatformViewsController implements PlatformViewsAccessibili } attachAccessibilityBridge(accessibilityBridge: AccessibilityBridge): void { - throw new Error('Method not implemented.'); + this.accessibilityEventsDelegate.setAccessibilityBridge(accessibilityBridge); } detachAccessibilityBridge(): void { - throw new Error('Method not implemented.'); + this.accessibilityEventsDelegate.setAccessibilityBridge(null); } createForPlatformViewLayer(request: PlatformViewCreationRequest): void { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets index 0e08f41fe9..015d195d7d 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets @@ -12,11 +12,63 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import AccessibilityChannel, {AccessibilityMessageHandler} from '../embedding/engine/systemchannels/AccessibilityChannel'; +import { ByteBuffer } from '../util/ByteBuffer'; +import Log from '../util/Log'; + +const TAG = "AccessibilityBridge"; + +export default class AccessibilityBridge implements AccessibilityMessageHandler { + + private accessibilityChannel: AccessibilityChannel | null = null; -export default class AccessibilityBridge { constructor(){ } + + announce(message: string): void { + throw new Error('Method not implemented.'); + // android -> rootAccessibilityView.announceForAccessibility(message); + } + + onTap(nodeId: number): void { + throw new Error('Method not implemented.'); + // android -> sendAccessibilityEvent(nodeId, AccessibilityEvent.TYPE_VIEW_CLICKED); + } + + onLongPress(nodeId: number): void { + throw new Error('Method not implemented.'); + // android -> sendAccessibilityEvent(nodeId, AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); + } + + onTooltip(nodeId: string): void { + throw new Error('Method not implemented.'); + // android -> AccessibilityEvent e = + // obtainAccessibilityEvent(ROOT_NODE_ID, AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + // e.getText().add(message); + // sendAccessibilityEvent(e); + } + + /** + * updateSemantics、updateCustomAccessibilityActions的debug流程,该过程只在native c++层实现,后续会删除 + * @param buffer + * @param strings + * @param stringAttributeArgs + */ + updateSemantics(buffer: ByteBuffer, strings: string[], stringAttributeArgs: ByteBuffer[]): void { + Log.d(TAG, "AccessibilityBridge.ets updateSemantics is called"); + } + + updateCustomAccessibilityActions(buffer: ByteBuffer, strings: string[]): void { + Log.d(TAG, "AccessibilityBridge.ets updateCustomAccessibilityActions is called"); + + } + + /** + * TODO lack of AccessibilityManager.AccessibilityStateChangeListener + * Listener that is notified when accessibility is turned on/off. + */ + } export enum Action { -- Gitee From 46558b8075b890878bfb7b61c28b09935f5534ae Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 28 Aug 2024 17:14:42 +0800 Subject: [PATCH 002/151] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Enative?= =?UTF-8?q?=E5=B1=82cpp=E4=BB=A3=E7=A0=81=EF=BC=8C=E5=8C=85=E6=8B=ACplatfo?= =?UTF-8?q?rm=5Fview=5Fohos-delegate=E5=92=8Cohos=5Faccessibility=5Fbridge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- lib/ui/window/platform_configuration.cc | 1 + runtime/runtime_controller.cc | 1 + shell/common/shell.cc | 1 + .../embedder/platform_view_embedder.cc | 1 + shell/platform/ohos/BUILD.gn | 4 + .../ohos_accessibility_bridge.cpp | 46 ++ .../accessibility/ohos_accessibility_bridge.h | 48 ++ shell/platform/ohos/library_loader.cpp | 14 +- .../ohos/napi/platform_view_ohos_napi.cpp | 428 ++++++++++-------- .../ohos/napi/platform_view_ohos_napi.h | 72 ++- shell/platform/ohos/platform_view_ohos.cpp | 97 ++-- shell/platform/ohos/platform_view_ohos.h | 3 + .../ohos/platform_view_ohos_delegate.cpp | 233 ++++++++++ .../ohos/platform_view_ohos_delegate.h | 46 ++ 14 files changed, 715 insertions(+), 280 deletions(-) create mode 100644 shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp create mode 100644 shell/platform/ohos/accessibility/ohos_accessibility_bridge.h create mode 100644 shell/platform/ohos/platform_view_ohos_delegate.cpp create mode 100644 shell/platform/ohos/platform_view_ohos_delegate.h diff --git a/lib/ui/window/platform_configuration.cc b/lib/ui/window/platform_configuration.cc index 5972d4aee9..296847f9aa 100644 --- a/lib/ui/window/platform_configuration.cc +++ b/lib/ui/window/platform_configuration.cc @@ -421,6 +421,7 @@ void PlatformConfigurationNativeApi::UpdateSemantics(SemanticsUpdate* update) { UIDartState::ThrowIfUIOperationsProhibited(); UIDartState::Current()->platform_configuration()->client()->UpdateSemantics( update); + FML_DLOG(INFO) << "PlatformConfigurationNativeApi::UpdateSemantics is called"; } Dart_Handle PlatformConfigurationNativeApi::ComputePlatformResolvedLocale( diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index 9870d5e780..07db7f9d71 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -317,6 +317,7 @@ void RuntimeController::Render(Scene* scene) { void RuntimeController::UpdateSemantics(SemanticsUpdate* update) { if (platform_data_.semantics_enabled) { client_.UpdateSemantics(update->takeNodes(), update->takeActions()); + FML_DLOG(INFO) << "RuntimeController::UpdateSemantics"; } } diff --git a/shell/common/shell.cc b/shell/common/shell.cc index bdaf8c234d..72358c8f59 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1215,6 +1215,7 @@ void Shell::OnEngineUpdateSemantics(SemanticsNodeUpdates update, actions = std::move(actions)] { if (view) { view->UpdateSemantics(update, actions); + FML_DLOG(INFO) << "Shell::OnEngineUpdateSemantics is called"; } }); } diff --git a/shell/platform/embedder/platform_view_embedder.cc b/shell/platform/embedder/platform_view_embedder.cc index 1cedc22810..12c3f83dbd 100644 --- a/shell/platform/embedder/platform_view_embedder.cc +++ b/shell/platform/embedder/platform_view_embedder.cc @@ -122,6 +122,7 @@ void PlatformViewEmbedder::UpdateSemantics( if (platform_dispatch_table_.update_semantics_callback != nullptr) { platform_dispatch_table_.update_semantics_callback(std::move(update), std::move(actions)); + FML_DLOG(INFO) << "PlatformViewEmbedder::UpdateSemantics is called"; } } diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn index 689f5015c2..9cdba5e014 100644 --- a/shell/platform/ohos/BUILD.gn +++ b/shell/platform/ohos/BUILD.gn @@ -84,6 +84,8 @@ source_set("flutter_ohos_sources") { "ohos_surface_gl_skia.h", "types.h", "ohos_logging.h", + "platform_view_ohos_delegate.h", + "./accessibility/ohos_accessibility_bridge.h" ] #configs += [ "//flutter/shell/platform/ohos/config:gtk" ] @@ -114,6 +116,8 @@ source_set("flutter_ohos_sources") { "ohos_image_generator.cpp", "ohos_external_texture_gl.cpp", "./surface/ohos_snapshot_surface_producer.cpp", + "platform_view_ohos_delegate.cpp", + "./accessibility/ohos_accessibility_bridge.cpp" ] # Set flag to stop headers being directly included (library users should not do this) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp new file mode 100644 index 0000000000..83d8096080 --- /dev/null +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development 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 "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" +#include "flutter/fml/logging.h" +// #include +// "flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h" + +namespace flutter { + +OhosAccessibilityBridge::OhosAccessibilityBridge() = default; +OhosAccessibilityBridge::~OhosAccessibilityBridge() = default; + +void OhosAccessibilityBridge::updateSemantics( // TODO debug sending test + std::vector buffer, + std::vector strings, + std::vector> string_attribute_args) { + FML_DLOG(INFO) << "buffer size: " << buffer.size() + << "strings size: " << strings.size() + << "string_attribute_args size: " << string_attribute_args.size(); + FML_DLOG(INFO) << ("Native C++ OhosAccessibilityBridge::updateSemantics"); +} + +void OhosAccessibilityBridge::updateCustomAccessibilityActions( + std::vector buffer, + std::vector strings) { + FML_DLOG(INFO) << "buffer size: " << buffer.size() + << "strings size: " << strings.size(); + FML_DLOG(INFO) + << ("Native C++ " + "OhosAccessibilityBridge::updateCustomAccessibilityActions"); +} + +} // namespace flutter diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h new file mode 100644 index 0000000000..925a202748 --- /dev/null +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development 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 OHOS_ACCESSIBILITY_BRIDGE_H +#define OHOS_ACCESSIBILITY_BRIDGE_H + +#include "flutter/fml/log_level.h" +// #include "flutter/fml/macros.h" +#include "flutter/lib/ui/semantics/semantics_node.h" +#include +#include +#include +#include + +namespace flutter { + +/** + * flutter和ohos的无障碍服务桥接 + */ +class OhosAccessibilityBridge { + public: + OhosAccessibilityBridge(); + ~OhosAccessibilityBridge(); + + void updateSemantics(std::vector buffer, + std::vector strings, + std::vector> string_attribute_args); + + void updateCustomAccessibilityActions(std::vector buffer, + std::vector strings); + + private: + std::unordered_map flutterSemanticsTree; +}; +} // namespace flutter +#endif // OHOS_ACCESSIBILITY_BRIDGE_H diff --git a/shell/platform/ohos/library_loader.cpp b/shell/platform/ohos/library_loader.cpp index 9106a4ace5..26e8007afd 100644 --- a/shell/platform/ohos/library_loader.cpp +++ b/shell/platform/ohos/library_loader.cpp @@ -17,8 +17,8 @@ #include "flutter/shell/platform/ohos/ohos_main.h" #include "napi/native_api.h" #include "napi_common.h" -#include "ohos_xcomponent_adapter.h" #include "ohos_logging.h" +#include "ohos_xcomponent_adapter.h" // namespace flutter { @@ -129,12 +129,16 @@ static napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_FUNCTION( "nativeSetTextureBackGroundPixelMap", flutter::PlatformViewOHOSNapi::nativeSetTextureBackGroundPixelMap), + DECLARE_NAPI_FUNCTION("nativeEncodeUtf8", + flutter::PlatformViewOHOSNapi::nativeEncodeUtf8), + DECLARE_NAPI_FUNCTION("nativeDecodeUtf8", + flutter::PlatformViewOHOSNapi::nativeDecodeUtf8), DECLARE_NAPI_FUNCTION( - "nativeEncodeUtf8", - flutter::PlatformViewOHOSNapi::nativeEncodeUtf8), + "nativeUpdateSemantics", + flutter::PlatformViewOHOSNapi::nativeUpdateSemantics), DECLARE_NAPI_FUNCTION( - "nativeDecodeUtf8", - flutter::PlatformViewOHOSNapi::nativeDecodeUtf8), + "nativeUpdateCustomAccessibilityActions", + flutter::PlatformViewOHOSNapi::nativeUpdateCustomAccessibilityActions), }; diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index 76a61090a8..9de18c094d 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -25,13 +25,13 @@ #include "flutter/fml/make_copyable.h" #include "flutter/fml/platform/ohos/napi_util.h" +#include "flutter/shell/platform/ohos/ohos_logging.h" #include "flutter/shell/platform/ohos/ohos_main.h" #include "flutter/shell/platform/ohos/ohos_shell_holder.h" +#include "flutter/shell/platform/ohos/ohos_xcomponent_adapter.h" #include "flutter/shell/platform/ohos/surface/ohos_native_window.h" #include "flutter/shell/platform/ohos/types.h" #include "unicode/uchar.h" -#include "flutter/shell/platform/ohos/ohos_xcomponent_adapter.h" -#include "flutter/shell/platform/ohos/ohos_logging.h" #define OHOS_SHELL_HOLDER (reinterpret_cast(shell_holder)) namespace flutter { @@ -415,9 +415,10 @@ void PlatformViewOHOSNapi::DecodeImage(int64_t imageGeneratorAddress, void* inputData, size_t dataSize) { FML_DLOG(INFO) << "start decodeImage"; - platform_task_runner_->PostTask(fml::MakeCopyable( - [imageGeneratorAddress_ = imageGeneratorAddress, - inputData_ = std::move(inputData), dataSize_ = dataSize, this]() mutable { + platform_task_runner_->PostTask( + fml::MakeCopyable([imageGeneratorAddress_ = imageGeneratorAddress, + inputData_ = std::move(inputData), + dataSize_ = dataSize, this]() mutable { napi_value callbackParam[2]; callbackParam[0] = @@ -435,7 +436,9 @@ void PlatformViewOHOSNapi::DecodeImage(int64_t imageGeneratorAddress, })); } -void PlatformViewOHOSNapi::FlutterViewOnTouchEvent(std::shared_ptr touchPacketString, int size) { +void PlatformViewOHOSNapi::FlutterViewOnTouchEvent( + std::shared_ptr touchPacketString, + int size) { if (touchPacketString == nullptr) { FML_LOG(ERROR) << "Input parameter error"; return; @@ -445,11 +448,13 @@ void PlatformViewOHOSNapi::FlutterViewOnTouchEvent(std::shared_ptr( OhosMain::Get().GetSettings(), napi_facade, platform_loop); if (shell_holder->IsValid()) { - int64_t shell_holder_value = - reinterpret_cast(shell_holder.get()); + int64_t shell_holder_value = reinterpret_cast(shell_holder.get()); FML_DLOG(INFO) << "PlatformViewOHOSNapi shell_holder:" << shell_holder_value; napi_value id; @@ -596,7 +600,8 @@ napi_value PlatformViewOHOSNapi::nativeGetPixelMap(napi_env env, /** * 从当前的flutterNapi复制一个新的实例 */ -napi_value PlatformViewOHOSNapi::nativeSpawn(napi_env env, napi_callback_info info) { +napi_value PlatformViewOHOSNapi::nativeSpawn(napi_env env, + napi_callback_info info) { napi_status ret; size_t argc = 6; napi_value args[6] = {nullptr}; @@ -636,12 +641,14 @@ napi_value PlatformViewOHOSNapi::nativeSpawn(napi_env env, napi_callback_info in LOGD(" initialRoute: %{public}s", initial_route.c_str()); std::vector entrypoint_args; - if (fml::napi::SUCCESS != fml::napi::GetArrayString(env, args[4], entrypoint_args)) { + if (fml::napi::SUCCESS != + fml::napi::GetArrayString(env, args[4], entrypoint_args)) { LOGE("nativeRunBundleAndSnapshotFromLibrary GetArrayString error"); return nullptr; } - std::shared_ptr napi_facade = std::make_shared(env); + std::shared_ptr napi_facade = + std::make_shared(env); napi_create_reference(env, args[5], 1, &(napi_facade->ref_napi_obj_)); auto spawned_shell_holder = OHOS_SHELL_HOLDER->Spawn( @@ -653,7 +660,9 @@ napi_value PlatformViewOHOSNapi::nativeSpawn(napi_env env, napi_callback_info in } napi_value shell_holder_id; - napi_create_int64(env, reinterpret_cast(spawned_shell_holder.release()), &shell_holder_id); + napi_create_int64(env, + reinterpret_cast(spawned_shell_holder.release()), + &shell_holder_id); return shell_holder_id; } @@ -1447,9 +1456,8 @@ napi_value PlatformViewOHOSNapi::nativeGetSystemLanguages( napi_value PlatformViewOHOSNapi::nativeInitNativeImage( napi_env env, - napi_callback_info info) -{ - FML_DLOG(INFO)<<"PlatformViewOHOSNapi::nativeInitNativeImage"; + napi_callback_info info) { + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeInitNativeImage"; size_t argc = 3; napi_value args[3] = {nullptr}; int64_t shell_holder; @@ -1457,17 +1465,17 @@ napi_value PlatformViewOHOSNapi::nativeInitNativeImage( NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); NAPI_CALL(env, napi_get_value_int64(env, args[0], &shell_holder)); NAPI_CALL(env, napi_get_value_int64(env, args[1], &textureId)); - ImageNative *imageNative = OH_Image_InitImageNative(env, args[2]); + ImageNative* imageNative = OH_Image_InitImageNative(env, args[2]); // std::unique_ptr uImage; - OHOS_SHELL_HOLDER->GetPlatformView()->RegisterExternalTextureByImage(textureId, imageNative); + OHOS_SHELL_HOLDER->GetPlatformView()->RegisterExternalTextureByImage( + textureId, imageNative); return nullptr; } napi_value PlatformViewOHOSNapi::nativeRegisterTexture( napi_env env, - napi_callback_info info) -{ - FML_DLOG(INFO)<<"PlatformViewOHOSNapi::nativeRegisterTexture"; + napi_callback_info info) { + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeRegisterTexture"; size_t argc = 2; napi_value args[2] = {nullptr}; int64_t shell_holder; @@ -1475,17 +1483,17 @@ napi_value PlatformViewOHOSNapi::nativeRegisterTexture( NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); NAPI_CALL(env, napi_get_value_int64(env, args[0], &shell_holder)); NAPI_CALL(env, napi_get_value_int64(env, args[1], &textureId)); - int64_t surfaceId = OHOS_SHELL_HOLDER->GetPlatformView()->RegisterExternalTexture(textureId); + int64_t surfaceId = + OHOS_SHELL_HOLDER->GetPlatformView()->RegisterExternalTexture(textureId); napi_value res; napi_create_int64(env, surfaceId, &res); return res; } napi_value PlatformViewOHOSNapi::nativeUnregisterTexture( - napi_env env, - napi_callback_info info) -{ - FML_DLOG(INFO)<<"PlatformViewOHOSNapi::nativeUnregisterTexture"; + napi_env env, + napi_callback_info info) { + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeUnregisterTexture"; size_t argc = 2; napi_value args[2] = {nullptr}; int64_t shell_holder; @@ -1498,9 +1506,8 @@ napi_value PlatformViewOHOSNapi::nativeUnregisterTexture( } napi_value PlatformViewOHOSNapi::nativeMarkTextureFrameAvailable( - napi_env env, - napi_callback_info info) -{ + napi_env env, + napi_callback_info info) { size_t argc = 2; napi_value args[2] = {nullptr}; int64_t shell_holder; @@ -1513,10 +1520,9 @@ napi_value PlatformViewOHOSNapi::nativeMarkTextureFrameAvailable( } napi_value PlatformViewOHOSNapi::nativeRegisterPixelMap( - napi_env env, - napi_callback_info info) -{ - FML_DLOG(INFO)<<"PlatformViewOHOSNapi::nativeRegisterPixelMap"; + napi_env env, + napi_callback_info info) { + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeRegisterPixelMap"; size_t argc = 3; napi_value args[3] = {nullptr}; int64_t shell_holder; @@ -1524,16 +1530,16 @@ napi_value PlatformViewOHOSNapi::nativeRegisterPixelMap( NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); NAPI_CALL(env, napi_get_value_int64(env, args[0], &shell_holder)); NAPI_CALL(env, napi_get_value_int64(env, args[1], &textureId)); - NativePixelMap *nativePixelMap = OH_PixelMap_InitNativePixelMap(env, args[2]); - OHOS_SHELL_HOLDER->GetPlatformView()->RegisterExternalTextureByPixelMap(textureId, nativePixelMap); + NativePixelMap* nativePixelMap = OH_PixelMap_InitNativePixelMap(env, args[2]); + OHOS_SHELL_HOLDER->GetPlatformView()->RegisterExternalTextureByPixelMap( + textureId, nativePixelMap); return nullptr; } napi_value PlatformViewOHOSNapi::nativeSetTextureBackGroundPixelMap( - napi_env env, - napi_callback_info info) -{ - FML_DLOG(INFO)<<"PlatformViewOHOSNapi::nativeSetTextureBackGroundPixelMap"; + napi_env env, + napi_callback_info info) { + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeSetTextureBackGroundPixelMap"; size_t argc = 3; napi_value args[3] = {nullptr}; int64_t shell_holder; @@ -1541,8 +1547,9 @@ napi_value PlatformViewOHOSNapi::nativeSetTextureBackGroundPixelMap( NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); NAPI_CALL(env, napi_get_value_int64(env, args[0], &shell_holder)); NAPI_CALL(env, napi_get_value_int64(env, args[1], &textureId)); - NativePixelMap *nativePixelMap = OH_PixelMap_InitNativePixelMap(env, args[2]); - OHOS_SHELL_HOLDER->GetPlatformView()->SetExternalTextureBackGroundPixelMap(textureId, nativePixelMap); + NativePixelMap* nativePixelMap = OH_PixelMap_InitNativePixelMap(env, args[2]); + OHOS_SHELL_HOLDER->GetPlatformView()->SetExternalTextureBackGroundPixelMap( + textureId, nativePixelMap); return nullptr; } @@ -1577,36 +1584,41 @@ void PlatformViewOHOSNapi::SetPlatformTaskRunner( */ napi_value PlatformViewOHOSNapi::nativeXComponentAttachFlutterEngine( napi_env env, - napi_callback_info info){ - napi_status ret; - size_t argc = 2; - napi_value args[2] = {nullptr}; - std::string xcomponent_id; - int64_t shell_holder; - ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - if (ret != napi_ok) { - FML_DLOG(ERROR) << "nativeXComponentAttachFlutterEngine napi_get_cb_info error:" - << ret; - return nullptr; - } + napi_callback_info info) { + napi_status ret; + size_t argc = 2; + napi_value args[2] = {nullptr}; + std::string xcomponent_id; + int64_t shell_holder; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + FML_DLOG(ERROR) + << "nativeXComponentAttachFlutterEngine napi_get_cb_info error:" << ret; + return nullptr; + } - if (fml::napi::GetString(env, args[0], xcomponent_id) != 0) { - FML_DLOG(ERROR) << "nativeXComponentAttachFlutterEngine xcomponent_id GetString error"; - return nullptr; - } + if (fml::napi::GetString(env, args[0], xcomponent_id) != 0) { + FML_DLOG(ERROR) + << "nativeXComponentAttachFlutterEngine xcomponent_id GetString error"; + return nullptr; + } - ret = napi_get_value_int64(env, args[1], &shell_holder); - if (ret != napi_ok) { - FML_DLOG(ERROR) << "nativeXComponentAttachFlutterEngine shell_holder napi_get_value_int64 error"; - return nullptr; - } - std::string shell_holder_str = std::to_string(shell_holder); + ret = napi_get_value_int64(env, args[1], &shell_holder); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "nativeXComponentAttachFlutterEngine shell_holder " + "napi_get_value_int64 error"; + return nullptr; + } + std::string shell_holder_str = std::to_string(shell_holder); - LOGD("nativeXComponentAttachFlutterEngine xcomponent_id: %{public}s, shell_holder: %{public}ld ", - xcomponent_id.c_str(), shell_holder); + LOGD( + "nativeXComponentAttachFlutterEngine xcomponent_id: %{public}s, " + "shell_holder: %{public}ld ", + xcomponent_id.c_str(), shell_holder); - XComponentAdapter::GetInstance()->AttachFlutterEngine(xcomponent_id, shell_holder_str); - return nullptr; + XComponentAdapter::GetInstance()->AttachFlutterEngine(xcomponent_id, + shell_holder_str); + return nullptr; } /** * @brief xcomponent解除flutter引擎绑定 @@ -1617,31 +1629,34 @@ napi_value PlatformViewOHOSNapi::nativeXComponentAttachFlutterEngine( */ napi_value PlatformViewOHOSNapi::nativeXComponentDetachFlutterEngine( napi_env env, - napi_callback_info info){ - napi_status ret; - size_t argc = 2; - napi_value args[2] = {nullptr}; - std::string xcomponent_id; - int64_t shell_holder; - ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - if (ret != napi_ok) { - FML_DLOG(ERROR) << "nativeXComponentAttachFlutterEngine napi_get_cb_info error:" - << ret; - return nullptr; - } - if (fml::napi::GetString(env, args[0], xcomponent_id) != 0) { - FML_DLOG(ERROR) << "nativeXComponentAttachFlutterEngine xcomponent_id GetString error"; - return nullptr; - } - ret = napi_get_value_int64(env, args[1], &shell_holder); - if (ret != napi_ok) { - FML_DLOG(ERROR) << "nativeXComponentAttachFlutterEngine shell_holder napi_get_value_int64 error"; - return nullptr; - } - - LOGD("nativeXComponentDetachFlutterEngine xcomponent_id: %{public}s", xcomponent_id.c_str()); - XComponentAdapter::GetInstance()->DetachFlutterEngine(xcomponent_id); + napi_callback_info info) { + napi_status ret; + size_t argc = 2; + napi_value args[2] = {nullptr}; + std::string xcomponent_id; + int64_t shell_holder; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + FML_DLOG(ERROR) + << "nativeXComponentAttachFlutterEngine napi_get_cb_info error:" << ret; return nullptr; + } + if (fml::napi::GetString(env, args[0], xcomponent_id) != 0) { + FML_DLOG(ERROR) + << "nativeXComponentAttachFlutterEngine xcomponent_id GetString error"; + return nullptr; + } + ret = napi_get_value_int64(env, args[1], &shell_holder); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "nativeXComponentAttachFlutterEngine shell_holder " + "napi_get_value_int64 error"; + return nullptr; + } + + LOGD("nativeXComponentDetachFlutterEngine xcomponent_id: %{public}s", + xcomponent_id.c_str()); + XComponentAdapter::GetInstance()->DetachFlutterEngine(xcomponent_id); + return nullptr; } /** @@ -1657,74 +1672,82 @@ napi_value PlatformViewOHOSNapi::nativeXComponentDetachFlutterEngine( * @param timestamp: number * @return napi_value */ -napi_value PlatformViewOHOSNapi::nativeXComponentDispatchMouseWheel(napi_env env, napi_callback_info info) -{ - napi_status ret; - size_t argc = 8; - napi_value args[8] = {nullptr}; - int64_t shellHolder; - std::string xcomponentId; - std::string eventType; - int64_t fingerId; - double globalX; - double globalY; - double offsetY; - int64_t timestamp; - ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - if (ret != napi_ok) { - FML_DLOG(ERROR) << "nativeXComponentDispatchMouseWheel napi_get_cb_info error:" - << ret; - return nullptr; - } - ret = napi_get_value_int64(env, args[0], &shellHolder); - if (ret != napi_ok) { - LOGE("nativeXComponentDispatchMouseWheel shellHolder napi_get_value_int64 error"); - return nullptr; - } - if (fml::napi::GetString(env, args[1], xcomponentId) != 0) { - FML_DLOG(ERROR) << "nativeXComponentDispatchMouseWheel xcomponentId GetString error"; - return nullptr; - } - if (fml::napi::GetString(env, args[2], eventType) != 0) { - FML_DLOG(ERROR) << "nativeXComponentDispatchMouseWheel eventType GetString error"; - return nullptr; - } - ret = napi_get_value_int64(env, args[3], &fingerId); - if (ret != napi_ok) { - LOGE("nativeXComponentDispatchMouseWheel fingerId napi_get_value_int64 error"); - return nullptr; - } - ret = napi_get_value_double(env, args[4], &globalX); - if (ret != napi_ok) { - LOGE("nativeXComponentDispatchMouseWheel globalX napi_get_value_double error"); - return nullptr; - } - ret = napi_get_value_double(env, args[5], &globalY); - if (ret != napi_ok) { - LOGE("nativeXComponentDispatchMouseWheel globalY napi_get_value_double error"); - return nullptr; - } - ret = napi_get_value_double(env, args[6], &offsetY); - if (ret != napi_ok) { - LOGE("nativeXComponentDispatchMouseWheel offsetY napi_get_value_double error"); - return nullptr; - } - ret = napi_get_value_int64(env, args[7], ×tamp); - if (ret != napi_ok) { - LOGE("nativeXComponentDispatchMouseWheel timestamp napi_get_value_int64 error"); - return nullptr; - } - flutter::mouseWheelEvent event { - eventType, - shellHolder, - fingerId, - globalX, - globalY, - offsetY, - timestamp - }; - XComponentAdapter::GetInstance()->OnMouseWheel(xcomponentId, event); +napi_value PlatformViewOHOSNapi::nativeXComponentDispatchMouseWheel( + napi_env env, + napi_callback_info info) { + napi_status ret; + size_t argc = 8; + napi_value args[8] = {nullptr}; + int64_t shellHolder; + std::string xcomponentId; + std::string eventType; + int64_t fingerId; + double globalX; + double globalY; + double offsetY; + int64_t timestamp; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + FML_DLOG(ERROR) + << "nativeXComponentDispatchMouseWheel napi_get_cb_info error:" << ret; + return nullptr; + } + ret = napi_get_value_int64(env, args[0], &shellHolder); + if (ret != napi_ok) { + LOGE( + "nativeXComponentDispatchMouseWheel shellHolder napi_get_value_int64 " + "error"); + return nullptr; + } + if (fml::napi::GetString(env, args[1], xcomponentId) != 0) { + FML_DLOG(ERROR) + << "nativeXComponentDispatchMouseWheel xcomponentId GetString error"; + return nullptr; + } + if (fml::napi::GetString(env, args[2], eventType) != 0) { + FML_DLOG(ERROR) + << "nativeXComponentDispatchMouseWheel eventType GetString error"; return nullptr; + } + ret = napi_get_value_int64(env, args[3], &fingerId); + if (ret != napi_ok) { + LOGE( + "nativeXComponentDispatchMouseWheel fingerId napi_get_value_int64 " + "error"); + return nullptr; + } + ret = napi_get_value_double(env, args[4], &globalX); + if (ret != napi_ok) { + LOGE( + "nativeXComponentDispatchMouseWheel globalX napi_get_value_double " + "error"); + return nullptr; + } + ret = napi_get_value_double(env, args[5], &globalY); + if (ret != napi_ok) { + LOGE( + "nativeXComponentDispatchMouseWheel globalY napi_get_value_double " + "error"); + return nullptr; + } + ret = napi_get_value_double(env, args[6], &offsetY); + if (ret != napi_ok) { + LOGE( + "nativeXComponentDispatchMouseWheel offsetY napi_get_value_double " + "error"); + return nullptr; + } + ret = napi_get_value_int64(env, args[7], ×tamp); + if (ret != napi_ok) { + LOGE( + "nativeXComponentDispatchMouseWheel timestamp napi_get_value_int64 " + "error"); + return nullptr; + } + flutter::mouseWheelEvent event{eventType, shellHolder, fingerId, globalX, + globalY, offsetY, timestamp}; + XComponentAdapter::GetInstance()->OnMouseWheel(xcomponentId, event); + return nullptr; } /** @@ -1733,27 +1756,29 @@ napi_value PlatformViewOHOSNapi::nativeXComponentDispatchMouseWheel(napi_env env * @param str: string * @return napi_value */ -napi_value PlatformViewOHOSNapi::nativeEncodeUtf8(napi_env env, napi_callback_info info) -{ - size_t argc = 1; - napi_value args[1] = {nullptr}; - napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - - size_t length = 0; - napi_get_value_string_utf8(env, args[0], nullptr, 0, &length); - - auto null_terminated_length = length + 1; - auto char_array = std::make_unique(null_terminated_length); - napi_get_value_string_utf8(env, args[0], char_array.get(), null_terminated_length, nullptr); - - void *data; - napi_value arraybuffer; - napi_create_arraybuffer(env, length, &data, &arraybuffer); - std::memcpy(data, char_array.get(), length); - - napi_value uint8_array; - napi_create_typedarray(env, napi_uint8_array, length, arraybuffer, 0, &uint8_array); - return uint8_array; +napi_value PlatformViewOHOSNapi::nativeEncodeUtf8(napi_env env, + napi_callback_info info) { + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + size_t length = 0; + napi_get_value_string_utf8(env, args[0], nullptr, 0, &length); + + auto null_terminated_length = length + 1; + auto char_array = std::make_unique(null_terminated_length); + napi_get_value_string_utf8(env, args[0], char_array.get(), + null_terminated_length, nullptr); + + void* data; + napi_value arraybuffer; + napi_create_arraybuffer(env, length, &data, &arraybuffer); + std::memcpy(data, char_array.get(), length); + + napi_value uint8_array; + napi_create_typedarray(env, napi_uint8_array, length, arraybuffer, 0, + &uint8_array); + return uint8_array; } /** @@ -1762,19 +1787,36 @@ napi_value PlatformViewOHOSNapi::nativeEncodeUtf8(napi_env env, napi_callback_in * @param array: Uint8Array * @return napi_value */ -napi_value PlatformViewOHOSNapi::nativeDecodeUtf8(napi_env env, napi_callback_info info) -{ - size_t argc = 1; - napi_value args[1] = {nullptr}; - napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - - size_t size = 0; - void *data = nullptr; - napi_get_typedarray_info(env, args[0], nullptr, &size, &data, nullptr, nullptr); - - napi_value result; - napi_create_string_utf8(env, static_cast(data), size, &result); - return result; +napi_value PlatformViewOHOSNapi::nativeDecodeUtf8(napi_env env, + napi_callback_info info) { + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + size_t size = 0; + void* data = nullptr; + napi_get_typedarray_info(env, args[0], nullptr, &size, &data, nullptr, + nullptr); + + napi_value result; + napi_create_string_utf8(env, static_cast(data), size, &result); + return result; +} + +napi_value PlatformViewOHOSNapi::nativeUpdateSemantics( + napi_env env, + napi_callback_info info) { + // TODO ets calls c++ + + return nullptr; +} + +napi_value PlatformViewOHOSNapi::nativeUpdateCustomAccessibilityActions( + napi_env env, + napi_callback_info info) { + // TODO ets calls c++ + + return nullptr; } } // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h index a155048ec5..3e54845081 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.h +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -38,13 +38,13 @@ struct locale { }; struct mouseWheelEvent { - std::string eventType; - int64_t shellHolder; - int64_t fingerId; - double globalX; - double globalY; - double offsetY; - int64_t timestamp; + std::string eventType; + int64_t shellHolder; + int64_t fingerId; + double globalX; + double globalY; + double offsetY; + int64_t timestamp; }; class PlatformViewOHOSNapi { @@ -82,7 +82,8 @@ class PlatformViewOHOSNapi { void* inputData, size_t dataSize); - void FlutterViewOnTouchEvent(std::shared_ptr touchPacketString, int size); + void FlutterViewOnTouchEvent(std::shared_ptr touchPacketString, + int size); static napi_value nativeUpdateRefreshRate( napi_env env, @@ -155,37 +156,30 @@ class PlatformViewOHOSNapi { napi_env env, napi_callback_info info); // 应用下发系统语言设置 - static napi_value nativeInitNativeImage( - napi_env env, - napi_callback_info info); + static napi_value nativeInitNativeImage(napi_env env, + napi_callback_info info); - static napi_value nativeUnregisterTexture( - napi_env env, - napi_callback_info info); + static napi_value nativeUnregisterTexture(napi_env env, + napi_callback_info info); - static napi_value nativeMarkTextureFrameAvailable( - napi_env env, - napi_callback_info info); + static napi_value nativeMarkTextureFrameAvailable(napi_env env, + napi_callback_info info); - static napi_value nativeRegisterPixelMap( - napi_env env, - napi_callback_info info); + static napi_value nativeRegisterPixelMap(napi_env env, + napi_callback_info info); - static napi_value nativeSetTextureBackGroundPixelMap( - napi_env env, - napi_callback_info info); + static napi_value nativeSetTextureBackGroundPixelMap(napi_env env, + napi_callback_info info); - static napi_value nativeRegisterTexture( - napi_env env, - napi_callback_info info); + static napi_value nativeRegisterTexture(napi_env env, + napi_callback_info info); // Surface相关,XComponent调用 static void SurfaceCreated(int64_t shell_holder, void* window); - static void SurfaceChanged( - int64_t shell_holder, - int32_t width, - int32_t height); + static void SurfaceChanged(int64_t shell_holder, + int32_t width, + int32_t height); static void SurfaceDestroyed(int64_t shell_holder); static int64_t GetShellHolder(); @@ -195,13 +189,17 @@ class PlatformViewOHOSNapi { static napi_value nativeXComponentDetachFlutterEngine( napi_env env, napi_callback_info info); - static napi_value nativeXComponentDispatchMouseWheel( - napi_env env, - napi_callback_info info); - static napi_value nativeEncodeUtf8( - napi_env env, - napi_callback_info info); - static napi_value nativeDecodeUtf8( + static napi_value nativeXComponentDispatchMouseWheel(napi_env env, + napi_callback_info info); + static napi_value nativeEncodeUtf8(napi_env env, napi_callback_info info); + static napi_value nativeDecodeUtf8(napi_env env, napi_callback_info info); + + /** + * debug --> ets call c++ + */ + static napi_value nativeUpdateSemantics(napi_env env, + napi_callback_info info); + static napi_value nativeUpdateCustomAccessibilityActions( napi_env env, napi_callback_info info); diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index 34c6193685..4331e5f271 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -22,8 +22,9 @@ #include "flutter/shell/platform/ohos/ohos_surface_software.h" #include "flutter/shell/platform/ohos/platform_message_response_ohos.h" #include "napi_common.h" -#include "ohos_logging.h" #include "ohos_external_texture_gl.h" +#include "ohos_logging.h" +#include "flutter/shell/platform/ohos/platform_view_ohos_delegate.h" #include @@ -117,9 +118,11 @@ PlatformViewOHOS::PlatformViewOHOS( PlatformViewOHOS::~PlatformViewOHOS() { FML_LOG(INFO) << "PlatformViewOHOS::~PlatformViewOHOS"; - for (std::map::iterator it = contextDatas_.begin(); it != contextDatas_.end(); ++it) { + for (std::map::iterator it = contextDatas_.begin(); + it != contextDatas_.end(); ++it) { if (it->second != nullptr) { - OhosImageFrameData* data = reinterpret_cast(it->second); + OhosImageFrameData* data = + reinterpret_cast(it->second); delete data; data = nullptr; it->second = nullptr; @@ -199,8 +202,7 @@ void PlatformViewOHOS::SetDestroyed(bool isDestroyed) { } // |PlatformView| -void PlatformViewOHOS::NotifyDestroyed() -{ +void PlatformViewOHOS::NotifyDestroyed() { SetDestroyed(true); LOGI("PlatformViewOHOS NotifyDestroyed enter"); PlatformView::NotifyDestroyed(); @@ -294,7 +296,8 @@ void PlatformViewOHOS::UpdateAssetResolverByType( void PlatformViewOHOS::UpdateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { - FML_DLOG(INFO) << "UpdateSemantics"; + FML_DLOG(INFO) << "PlatformViewOHOS::UpdateSemantics"; + platform_view_ohos_delegate_->UpdateSemantics(update, actions); } // |PlatformView| @@ -421,17 +424,15 @@ void PlatformViewOHOS::FireFirstFrameCallback() { napi_facade_->FlutterViewOnFirstFrame(); } -void PlatformViewOHOS::RegisterExternalTextureByImage( - int64_t texture_id, - ImageNative* image) -{ +void PlatformViewOHOS::RegisterExternalTextureByImage(int64_t texture_id, + ImageNative* image) { if (ohos_context_->RenderingApi() == OHOSRenderingAPI::kOpenGLES) { auto iter = external_texture_gl_.find(texture_id); if (iter != external_texture_gl_.end()) { iter->second->DispatchImage(image); } else { std::shared_ptr ohos_external_gl = - std::make_shared(texture_id, ohos_surface_); + std::make_shared(texture_id, ohos_surface_); external_texture_gl_[texture_id] = ohos_external_gl; RegisterTexture(ohos_external_gl); ohos_external_gl->DispatchImage(image); @@ -445,14 +446,14 @@ PointerDataDispatcherMaker PlatformViewOHOS::GetDispatcherMaker() { }; } -uint64_t PlatformViewOHOS::RegisterExternalTexture(int64_t texture_id) -{ +uint64_t PlatformViewOHOS::RegisterExternalTexture(int64_t texture_id) { uint64_t surface_id = 0; int ret = -1; if (ohos_context_->RenderingApi() == OHOSRenderingAPI::kOpenGLES) { std::shared_ptr ohos_external_gl = - std::make_shared(texture_id, ohos_surface_); - ohos_external_gl->nativeImage_ = OH_NativeImage_Create(texture_id, GL_TEXTURE_EXTERNAL_OES); + std::make_shared(texture_id, ohos_surface_); + ohos_external_gl->nativeImage_ = + OH_NativeImage_Create(texture_id, GL_TEXTURE_EXTERNAL_OES); if (ohos_external_gl->nativeImage_ == nullptr) { FML_DLOG(ERROR) << "Error with OH_NativeImage_Create"; return surface_id; @@ -462,12 +463,15 @@ uint64_t PlatformViewOHOS::RegisterExternalTexture(int64_t texture_id) OH_OnFrameAvailableListener listener; listener.context = contextData; listener.onFrameAvailable = &PlatformViewOHOS::OnNativeImageFrameAvailable; - ret = OH_NativeImage_SetOnFrameAvailableListener(ohos_external_gl->nativeImage_, listener); + ret = OH_NativeImage_SetOnFrameAvailableListener( + ohos_external_gl->nativeImage_, listener); if (ret != 0) { - FML_DLOG(ERROR) << "Error with OH_NativeImage_SetOnFrameAvailableListener"; + FML_DLOG(ERROR) + << "Error with OH_NativeImage_SetOnFrameAvailableListener"; return surface_id; } - ret = OH_NativeImage_GetSurfaceId(ohos_external_gl->nativeImage_, &surface_id); + ret = OH_NativeImage_GetSurfaceId(ohos_external_gl->nativeImage_, + &surface_id); ohos_external_gl->first_update_ = false; if (ret != 0) { FML_DLOG(ERROR) << "Error with OH_NativeImage_GetSurfaceId"; @@ -479,48 +483,49 @@ uint64_t PlatformViewOHOS::RegisterExternalTexture(int64_t texture_id) return surface_id; } -void PlatformViewOHOS::OnNativeImageFrameAvailable(void *data) -{ - auto frameData = reinterpret_cast(data); +void PlatformViewOHOS::OnNativeImageFrameAvailable(void* data) { + auto frameData = reinterpret_cast(data); if (frameData == nullptr || frameData->context_ == nullptr) { - FML_DLOG(ERROR) << "OnNativeImageFrameAvailable, frameData or context_ is null."; + FML_DLOG(ERROR) + << "OnNativeImageFrameAvailable, frameData or context_ is null."; return; } if (frameData->context_->GetDestroyed()) { - FML_LOG(ERROR) << "OnNativeImageFrameAvailable NotifyDstroyed, will not MarkTextureFrameAvailable"; + FML_LOG(ERROR) << "OnNativeImageFrameAvailable NotifyDstroyed, will not " + "MarkTextureFrameAvailable"; return; } - std::shared_ptr ohos_surface = frameData->context_->ohos_surface_; + std::shared_ptr ohos_surface = + frameData->context_->ohos_surface_; const TaskRunners task_runners = frameData->context_->task_runners_; if (ohos_surface) { fml::TaskRunner::RunNowOrPostTask( - task_runners.GetPlatformTaskRunner(), - [frameData]() { + task_runners.GetPlatformTaskRunner(), [frameData]() { if (frameData->context_->GetDestroyed()) { - FML_LOG(ERROR) << "OnNativeImageFrameAvailable NotifyDstroyed, will not MarkTextureFrameAvailable"; + FML_LOG(ERROR) << "OnNativeImageFrameAvailable NotifyDstroyed, " + "will not MarkTextureFrameAvailable"; return; } - frameData->context_->MarkTextureFrameAvailable(frameData->texture_id_); + frameData->context_->MarkTextureFrameAvailable( + frameData->texture_id_); }); } } -void PlatformViewOHOS::UnRegisterExternalTexture(int64_t texture_id) -{ - FML_DLOG(INFO) << "PlatformViewOHOS::UnRegisterExternalTexture, texture_id=" << texture_id; +void PlatformViewOHOS::UnRegisterExternalTexture(int64_t texture_id) { + FML_DLOG(INFO) << "PlatformViewOHOS::UnRegisterExternalTexture, texture_id=" + << texture_id; external_texture_gl_.erase(texture_id); UnregisterTexture(texture_id); std::map::iterator it = contextDatas_.find(texture_id); if (it != contextDatas_.end()) { if (it->second != nullptr) { - OhosImageFrameData* data = reinterpret_cast(it->second); + OhosImageFrameData* data = + reinterpret_cast(it->second); task_runners_.GetPlatformTaskRunner()->PostDelayedTask( - [data_ = data]() { - delete data_; - }, - fml::TimeDelta::FromSeconds(2)); + [data_ = data]() { delete data_; }, fml::TimeDelta::FromSeconds(2)); data = nullptr; it->second = nullptr; } @@ -528,8 +533,9 @@ void PlatformViewOHOS::UnRegisterExternalTexture(int64_t texture_id) } } -void PlatformViewOHOS::RegisterExternalTextureByPixelMap(int64_t texture_id, NativePixelMap* pixelMap) -{ +void PlatformViewOHOS::RegisterExternalTextureByPixelMap( + int64_t texture_id, + NativePixelMap* pixelMap) { if (ohos_context_->RenderingApi() == OHOSRenderingAPI::kOpenGLES) { auto iter = external_texture_gl_.find(texture_id); if (iter != external_texture_gl_.end()) { @@ -545,8 +551,9 @@ void PlatformViewOHOS::RegisterExternalTextureByPixelMap(int64_t texture_id, Nat } } -void PlatformViewOHOS::SetExternalTextureBackGroundPixelMap(int64_t texture_id, NativePixelMap* pixelMap) -{ +void PlatformViewOHOS::SetExternalTextureBackGroundPixelMap( + int64_t texture_id, + NativePixelMap* pixelMap) { if (ohos_context_->RenderingApi() == OHOSRenderingAPI::kOpenGLES) { auto iter = external_texture_gl_.find(texture_id); if (iter != external_texture_gl_.end()) { @@ -555,14 +562,14 @@ void PlatformViewOHOS::SetExternalTextureBackGroundPixelMap(int64_t texture_id, } } -void PlatformViewOHOS::OnTouchEvent(const std::shared_ptr touchPacketString, int size) -{ +void PlatformViewOHOS::OnTouchEvent( + const std::shared_ptr touchPacketString, + int size) { return napi_facade_->FlutterViewOnTouchEvent(touchPacketString, size); } -OhosImageFrameData::OhosImageFrameData( - PlatformViewOHOS* context, - int64_t texture_id) +OhosImageFrameData::OhosImageFrameData(PlatformViewOHOS* context, + int64_t texture_id) : context_(context), texture_id_(texture_id) {} OhosImageFrameData::~OhosImageFrameData() = default; diff --git a/shell/platform/ohos/platform_view_ohos.h b/shell/platform/ohos/platform_view_ohos.h index cccbc04846..512efeb78a 100644 --- a/shell/platform/ohos/platform_view_ohos.h +++ b/shell/platform/ohos/platform_view_ohos.h @@ -35,6 +35,7 @@ #include "flutter/shell/platform/ohos/surface/ohos_snapshot_surface_producer.h" #include "flutter/shell/platform/ohos/surface/ohos_surface.h" #include "flutter/shell/platform/ohos/vsync_waiter_ohos.h" +#include "flutter/shell/platform/ohos/platform_view_ohos_delegate.h" namespace flutter { @@ -139,6 +140,8 @@ class PlatformViewOHOS final : public PlatformView { std::map> external_texture_gl_; std::map contextDatas_; + std::shared_ptr platform_view_ohos_delegate_; + static bool isDestroyed_; static pthread_mutex_t mutex_; diff --git a/shell/platform/ohos/platform_view_ohos_delegate.cpp b/shell/platform/ohos/platform_view_ohos_delegate.cpp new file mode 100644 index 0000000000..946ebd79c9 --- /dev/null +++ b/shell/platform/ohos/platform_view_ohos_delegate.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development 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 "flutter/shell/platform/ohos/platform_view_ohos_delegate.h" +#include + +namespace flutter { + +void putStringAttributesIntoBuffer( + const StringAttributes& attributes, + int32_t* buffer_int32, + size_t& position, + std::vector>& string_attribute_args) { + if (attributes.empty()) { + buffer_int32[position++] = -1; + return; + } + buffer_int32[position++] = attributes.size(); + for (const auto& attribute : attributes) { + buffer_int32[position++] = attribute->start; + buffer_int32[position++] = attribute->end; + buffer_int32[position++] = static_cast(attribute->type); + switch (attribute->type) { + case StringAttributeType::kSpellOut: + buffer_int32[position++] = -1; + break; + case StringAttributeType::kLocale: + buffer_int32[position++] = string_attribute_args.size(); + std::shared_ptr locale_attribute = + std::static_pointer_cast(attribute); + string_attribute_args.push_back( + {locale_attribute->locale.begin(), locale_attribute->locale.end()}); + break; + } + } +} + +PlatformViewOHOSDelegate::PlatformViewOHOSDelegate( + std::shared_ptr napi_facade) + : napi_facade_(std::move(napi_facade)) {}; + +void PlatformViewOHOSDelegate::UpdateSemantics( + const flutter::SemanticsNodeUpdates& update, + const flutter::CustomAccessibilityActionUpdates& actions) { + constexpr size_t kBytesPerNode = 47 * sizeof(int32_t); + constexpr size_t kBytesPerChild = sizeof(int32_t); + constexpr size_t kBytesPerCustomAction = sizeof(int32_t); + constexpr size_t kBytesPerAction = 4 * sizeof(int32_t); + constexpr size_t kBytesPerStringAttribute = 4 * sizeof(int32_t); + + { + size_t num_bytes = 0; + for (const auto& value : update) { + num_bytes += kBytesPerNode; + num_bytes += + value.second.childrenInTraversalOrder.size() * kBytesPerChild; + num_bytes += value.second.childrenInHitTestOrder.size() * kBytesPerChild; + num_bytes += value.second.customAccessibilityActions.size() * + kBytesPerCustomAction; + num_bytes += + value.second.labelAttributes.size() * kBytesPerStringAttribute; + num_bytes += + value.second.valueAttributes.size() * kBytesPerStringAttribute; + num_bytes += value.second.increasedValueAttributes.size() * + kBytesPerStringAttribute; + num_bytes += value.second.decreasedValueAttributes.size() * + kBytesPerStringAttribute; + num_bytes += + value.second.hintAttributes.size() * kBytesPerStringAttribute; + } + // encode the updated nodes/actions into bytebuffer/strings + std::vector buffer(num_bytes); + std::vector strings; + std::vector> string_attribute_args; + + int32_t* buffer_int32 = reinterpret_cast(&buffer[0]); + float* buffer_float32 = reinterpret_cast(&buffer[0]); + + size_t position = 0; + for (const auto& value : update) { + // make sure you update kBytesPerNode and/or kBytesPerChild above to + // match the number of values you are sending. + const flutter::SemanticsNode& node = value.second; + buffer_int32[position++] = node.id; + buffer_int32[position++] = node.flags; + buffer_int32[position++] = node.actions; + buffer_int32[position++] = node.maxValueLength; + buffer_int32[position++] = node.currentValueLength; + buffer_int32[position++] = node.textSelectionBase; + buffer_int32[position++] = node.textSelectionExtent; + buffer_int32[position++] = node.platformViewId; + buffer_int32[position++] = node.scrollChildren; + buffer_int32[position++] = node.scrollIndex; + buffer_float32[position++] = static_cast(node.scrollPosition); + buffer_float32[position++] = static_cast(node.scrollExtentMax); + buffer_float32[position++] = static_cast(node.scrollExtentMin); + if (node.label.empty()) { + buffer_int32[position++] = -1; + } else { + buffer_int32[position++] = strings.size(); + strings.push_back(node.label); + } + + putStringAttributesIntoBuffer(node.labelAttributes, buffer_int32, + position, string_attribute_args); + if (node.value.empty()) { + buffer_int32[position++] = -1; + } else { + buffer_int32[position++] = strings.size(); + strings.push_back(node.value); + } + + putStringAttributesIntoBuffer(node.valueAttributes, buffer_int32, + position, string_attribute_args); + if (node.increasedValue.empty()) { + buffer_int32[position++] = -1; + } else { + buffer_int32[position++] = strings.size(); + strings.push_back(node.increasedValue); + } + + putStringAttributesIntoBuffer(node.increasedValueAttributes, buffer_int32, + position, string_attribute_args); + if (node.decreasedValue.empty()) { + buffer_int32[position++] = -1; + } else { + buffer_int32[position++] = strings.size(); + strings.push_back(node.decreasedValue); + } + + putStringAttributesIntoBuffer(node.decreasedValueAttributes, buffer_int32, + position, string_attribute_args); + + if (node.hint.empty()) { + buffer_int32[position++] = -1; + } else { + buffer_int32[position++] = strings.size(); + strings.push_back(node.hint); + } + + putStringAttributesIntoBuffer(node.hintAttributes, buffer_int32, position, + string_attribute_args); + + if (node.tooltip.empty()) { + buffer_int32[position++] = -1; + } else { + buffer_int32[position++] = strings.size(); + strings.push_back(node.tooltip); + } + + buffer_int32[position++] = node.textDirection; + buffer_float32[position++] = node.rect.left(); + buffer_float32[position++] = node.rect.top(); + buffer_float32[position++] = node.rect.right(); + buffer_float32[position++] = node.rect.bottom(); + node.transform.getColMajor(&buffer_float32[position]); + position += 16; + + buffer_int32[position++] = node.childrenInTraversalOrder.size(); + for (int32_t child : node.childrenInTraversalOrder) { + buffer_int32[position++] = child; + } + + for (int32_t child : node.childrenInHitTestOrder) { + buffer_int32[position++] = child; + } + + buffer_int32[position++] = node.customAccessibilityActions.size(); + for (int32_t child : node.customAccessibilityActions) { + buffer_int32[position++] = child; + } + } + + // custom accessibility actions. + size_t num_action_bytes = actions.size() * kBytesPerAction; + std::vector actions_buffer(num_action_bytes); + int32_t* actions_buffer_int32 = + reinterpret_cast(&actions_buffer[0]); + + std::vector action_strings; + size_t actions_position = 0; + for (const auto& value : actions) { + // If you edit this code, make sure you update kBytesPerAction + // to match the number of values you are sending. + const flutter::CustomAccessibilityAction& action = value.second; + actions_buffer_int32[actions_position++] = action.id; + actions_buffer_int32[actions_position++] = action.overrideId; + if (action.label.empty()) { + actions_buffer_int32[actions_position++] = -1; + } else { + actions_buffer_int32[actions_position++] = action_strings.size(); + action_strings.push_back(action.label); + } + if (action.hint.empty()) { + actions_buffer_int32[actions_position++] = -1; + } else { + actions_buffer_int32[actions_position++] = action_strings.size(); + action_strings.push_back(action.hint); + } + } + + if (!actions_buffer.empty()) { + // napi_facade_->FlutterViewUpdateCustomAccessibilityActions(actions_buffer, + // action_strings); + ax_bridge_router_->updateCustomAccessibilityActions(actions_buffer, + action_strings); + FML_DLOG(INFO) << "PlatformViewOHOSDelegate::" + "updateCustomAccessibilityActions is called"; + } + + if (!buffer.empty()) { + // napi_facade_->FlutterViewUpdateSemantics(buffer, strings, + // string_attribute_args); + ax_bridge_router_->updateSemantics(buffer, strings, + string_attribute_args); + FML_DLOG(INFO) << "PlatformViewOHOSDelegate::UpdateSemantics is called"; + } + } +} + +} // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/platform_view_ohos_delegate.h b/shell/platform/ohos/platform_view_ohos_delegate.h new file mode 100644 index 0000000000..97f5d826fc --- /dev/null +++ b/shell/platform/ohos/platform_view_ohos_delegate.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development 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 SHELL_PLATFORM_OHOS_PLATFORM_VIEW_OHOS_DELEGATE +#define SHELL_PLATFORM_OHOS_PLATFORM_VIEW_OHOS_DELEGATE + +#include +#include +#include + +#include "flutter/shell/common/platform_view.h" +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" +#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" + +namespace flutter { + +class PlatformViewOHOSDelegate { + public: +// PlatformViewOHOSDelegate() = default; +// ~PlatformViewOHOSDelegate() = default; + + explicit PlatformViewOHOSDelegate( + std::shared_ptr napi_facade); + + void UpdateSemantics( + const flutter::SemanticsNodeUpdates& update, + const flutter::CustomAccessibilityActionUpdates& actions); + + private: + const std::shared_ptr napi_facade_; + const std::shared_ptr ax_bridge_router_; +}; +} // namespace flutter +#endif \ No newline at end of file -- Gitee From fa124407364544030a9d837dd4c9dcf6833c9c6d Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 29 Aug 2024 20:43:06 +0800 Subject: [PATCH 003/151] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84=E6=97=A0?= =?UTF-8?q?=E9=9A=9C=E7=A2=8Dbridge=E4=B8=ADupdateSemantics=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BF=AE=E6=94=B9=E9=83=A8?= =?UTF-8?q?=E5=88=86ets=E4=B8=AD=E5=85=B3=E4=BA=8E=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8D=E6=9C=8D=E5=8A=A1=E7=9A=84=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- shell/platform/ohos/BUILD.gn | 4 +- .../native_interface_accessibility.cpp | 5 + .../native_interface_accessibility.h | 923 ++++++++++++++++++ .../ohos_accessibility_bridge.cpp | 187 +++- .../accessibility/ohos_accessibility_bridge.h | 131 ++- .../src/main/cpp/types/libflutter/index.d.ets | 5 + .../main/ets/embedding/engine/FlutterNapi.ets | 6 +- shell/platform/ohos/platform_view_ohos.cpp | 4 +- shell/platform/ohos/platform_view_ohos.h | 2 + .../ohos/platform_view_ohos_delegate.cpp | 10 +- 10 files changed, 1240 insertions(+), 37 deletions(-) create mode 100644 shell/platform/ohos/accessibility/native_interface_accessibility.cpp create mode 100644 shell/platform/ohos/accessibility/native_interface_accessibility.h diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn index 9cdba5e014..1af34507dd 100644 --- a/shell/platform/ohos/BUILD.gn +++ b/shell/platform/ohos/BUILD.gn @@ -85,7 +85,7 @@ source_set("flutter_ohos_sources") { "types.h", "ohos_logging.h", "platform_view_ohos_delegate.h", - "./accessibility/ohos_accessibility_bridge.h" + "./accessibility/ohos_accessibility_bridge.h", ] #configs += [ "//flutter/shell/platform/ohos/config:gtk" ] @@ -117,7 +117,7 @@ source_set("flutter_ohos_sources") { "ohos_external_texture_gl.cpp", "./surface/ohos_snapshot_surface_producer.cpp", "platform_view_ohos_delegate.cpp", - "./accessibility/ohos_accessibility_bridge.cpp" + "./accessibility/ohos_accessibility_bridge.cpp", ] # Set flag to stop headers being directly included (library users should not do this) diff --git a/shell/platform/ohos/accessibility/native_interface_accessibility.cpp b/shell/platform/ohos/accessibility/native_interface_accessibility.cpp new file mode 100644 index 0000000000..b56cac9704 --- /dev/null +++ b/shell/platform/ohos/accessibility/native_interface_accessibility.cpp @@ -0,0 +1,5 @@ +#include "flutter/shell/platform/ohos/accessibility/native_interface_accessibility.h" + +namespace flutter { + +} \ No newline at end of file diff --git a/shell/platform/ohos/accessibility/native_interface_accessibility.h b/shell/platform/ohos/accessibility/native_interface_accessibility.h new file mode 100644 index 0000000000..3ea3ef9d26 --- /dev/null +++ b/shell/platform/ohos/accessibility/native_interface_accessibility.h @@ -0,0 +1,923 @@ +/* + * 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. + */ + +/** + * @addtogroup ArkUI_Accessibility + * @{ + * + * @brief + * + * @since 13 + * @version 1.0 + */ + +/** + * @file native_interface_accessibility.h + * + * @brief + * + * @since 13 + * @version 1.0 + */ +#ifndef _NATIVE_INTERFACE_ACCESSIBILITY_H +#define _NATIVE_INTERFACE_ACCESSIBILITY_H + +#include + +#ifdef __cplusplus +extern "C"{ +#endif + +/** + * @brief Provides an encapsulated ArkUI_AccessibilityElementInfo instance. + * + * @since 13 + */ +typedef struct ArkUI_AccessibilityElementInfo ArkUI_AccessibilityElementInfo; + +/** + * @brief Defines the accessibility event info. + * + * @since 13 + */ +typedef struct ArkUI_AccessibilityEventInfo ArkUI_AccessibilityEventInfo; + +/** + * @brief Definesthe accessibility native provider. + * + * @since 13 + */ +typedef struct ArkUI_AccessibilityProvider ArkUI_AccessibilityProvider; + +/** + * @brief Provides an encapsulated OH_NativeAccessibilityDictionary instance, Implement the function of cpp dictionary. + * + * @since 13 + * @version 1.0 + */ +typedef struct ArkUI_AccessibilityActionArguments ArkUI_AccessibilityActionArguments; + +/** + * @brief Enumerates the API accessibility actions. + * + * @since 13 + * @version 1.0 + */ +typedef enum { + /** Invalid */ + ARKUI_NATIVE_ACCESSIBILITY_ACTION_INVALID = 0, + /** After receiving the event, the component needs to respond to the click. */ + ARKUI_NATIVE_ACCESSIBILITY_ACTION_CLICK = 0x00000010, + /** After receiving the event, the component needs to respond to the long click. */ + ARKUI_NATIVE_ACCESSIBILITY_ACTION_LONG_CLICK = 0x00000020, + /** Indicates the operation of obtaining the accessibility focus. The specific component is focused */ + ARKUI_NATIVE_ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS = 0x00000040, + /** Indicates the operation of clearing the accessibility focus. */ + ARKUI_NATIVE_ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080, + /** The scrolling component responds to forward scrolling action. */ + ARKUI_NATIVE_ACCESSIBILITY_ACTION_SCROLL_FORWARD = 0x00000100, + /** The scrolling component responds to backwrad scrolling action. */ + ARKUI_NATIVE_ACCESSIBILITY_ACTION_SCROLL_BACKWARD = 0x00000200, + /** Coping the selected content for the text component. */ + ARKUI_NATIVE_ACCESSIBILITY_ACTION_COPY = 0x00000400, + /** Paste the selected content for the text component. */ + ARKUI_NATIVE_ACCESSIBILITY_ACTION_PASTE = 0x00000800, + /** Cut the selected content for the text component. */ + ARKUI_NATIVE_ACCESSIBILITY_ACTION_CUT = 0x00001000, + /** Indicates the selection operation. The selectTextBegin, selectTextEnd, and selectTextInForWard parameters need to be set. Select a text segment in the edit box. */ + ARKUI_NATIVE_ACCESSIBILITY_ACTION_SET_SELECTION = 0x00002000, + /** Set the text Content for the text component. */ + ARKUI_NATIVE_ACCESSIBILITY_ACTION_SET_TEXT = 0x00004000, + /** Set the cursor position for the text component. */ + ARKUI_NATIVE_ACCESSIBILITY_ACTION_SET_CURSOR_POSITION = 0x00100000, +} ArkUI_Accessibility_ActionType; + +/** + * @brief Enumerates the API accessibility event types. + * + * @since 13 + * @version 1.0 + */ +typedef enum { + /** Invalid */ + ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_INVALID = 0, + /** Clicked event, which is sent after the UI component responds. */ + ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_CLICKED_EVENT = 0x00000001, + /** Long-Clicked event, which is sent after the UI component responds. */ + ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_LONG_CLICKED_EVENT = 0x00000002, + /** Selected event, which is sent after the UI component responds. */ + ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_SELECTED_EVENT = 0x00000004, + /** Text update event, needs to be send when the text is updated. */ + ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_TEXT_UPDATE_EVENT = 0x00000010, + /** Page update event, which is sent when the page jumps, switchs, changes in size, or moves. */ + ARKUI_NATIVE_ACCESSIBILITY_TYPE_PAGE_STATE_UPDATE = 0x00000020, + /** Content update event, which is sent when the page content changes. */ + ARKUI_NATIVE_ACCESSIBILITY_TYPE_PAGE_CONTENT_UPDATE = 0x00000800, + /** scrolled event, this event is send when a scrolling event occurs on a component that can be scrolled. */ + ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_SCROLLED_EVENT = 0x000001000, + /** Accessibility focus event, which is send after the UI component responds. */ + ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_ACCESSIBILITY_FOCUSED_EVENT = 0x00008000, + /** Accessibility focus clear event, which is send after the UI component responds. */ + ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED_EVENT = 0x00010000, + /** Request focus for accessibility event, proactively reqeust to focus on a specified node. */ + ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_REQUEST_FOCUS_FOR_ACCESSIBILITY = 0x02000000, + /** Page open event. the event is reported when the UI component */ + ARKUI_NATIVE_ACCESSIBILITY_TYPE_PAGE_OPEN = 0x20000000, + /** Page close event. the event is reported when the UI component */ + ARKUI_NATIVE_ACCESSIBILITY_TYPE_PAGE_CLOSE = 0x08000000, + /** Announce for accessibility event, requesting to actively play the specified content event. */ + ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_ANNOUNCE_FOR_ACCESSIBILITY = 0x10000000, +} ArkUI_AccessibilityEventType; + +/** + * @brief Defines the accessible of action + * + * @since 13 + * @version 1.0 + */ +typedef struct { + /** action type. */ + ArkUI_Accessibility_ActionType actionType; + /** the description message of action. */ + const char* description; +} ArkUI_AccessibleAction; + +/** + * @brief Defines the accessible of rect. + * + * @since 13 + * @version 1.0 + */ +typedef struct { + /** the left top x pixel corrdinates. */ + int32_t leftTopX; + /** the left top y pixel corrdinates. */ + int32_t leftTopY; + /** the right bottom x pixel corrdinates. */ + int32_t rightBottomX; + /** the right bottom y pixel corrdinates. */ + int32_t rightBottomY; +} ArkUI_AccessibleRect; + +/** + * @brief Defines the accessible of range info. + * + * @since 13 + * @version 1.0 + */ +typedef struct { + /** the min value. */ + double min; + /** the max value. */ + double max; + /** the current value. */ + double current; +} ArkUI_AccessibleRangeInfo; + +/** + * @brief Defines the accessible of grid info. + * + * @since 13 + * @version 1.0 + */ +typedef struct { + /** The number of row. */ + int32_t rowCount; + /** The number of column. */ + int32_t columnCount; + /** 0: select one line only, otherwise select multilines. */ + int32_t selectionMode; +} ArkUI_AccessibleGridInfo; + +/** + * @brief Defines the accessible of grid item info. + * + * @since 13 + * @version 1.0 + */ +typedef struct { + /** true: The item isHeading, otherwise is not */ + bool heading; + /** true: The item selected, otherwise is not */ + bool selected; + /** the index of column */ + int32_t columnIndex; + /** the index of row */ + int32_t rowIndex; + /** the column spanned */ + int32_t columnSpan; + /** the row spanned */ + int32_t rowSpan; +} ArkUI_AccessibleGridItemInfo; + +/** + * @brief Enumerates the API accessibility ErrorCode states. + * + * @since 13 + * @version 1.0 + */ +enum AcessbilityErrorCode{ + /** Successful. */ + OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS = 0, + /** Failed. */ + OH_ARKUI_ACCESSIBILITY_RESULT_FAILED = -1, + /** Invalid parameters. */ + OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER = -2, + /** Out of memory. */ + OH_ARKUI_ACCESSIBILITY_RESULT_OUT_OF_MEMORY = -3, +} ; + +/** + * @brief Enumerates the API accessibility search mode. + * + * @since 13 + * @version 1.0 + */ +typedef enum { + /** predecessors */ + NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS = 1 << 0, + /** slbings */ + NATIVE_SEARCH_MODE_PREFETCH_SIBLINGS = 1 << 1, + /** children */ + NATIVE_SEARCH_MODE_PREFETCH_CHILDREN = 1 << 2, + /** recusive children */ + NATIVE_SEARCH_MODE_PREFETCH_RECURSIVE_CHILDREN = 1 << 3, +} ArkUI_AccessibilitySearchMode; + +/** + * @brief Enumerates the API accessibility focus type. + * + * @since 13 + * @version 1.0 + */ +typedef enum { + /** Invalid */ + NATIVE_FOCUS_TYPE_INVALID = -1, + /** Input focus type */ + NATIVE_FOCUS_TYPE_INPUT = 1 << 0, + /** Accessibility focus type */ + NATIVE_FOCUS_TYPE_ACCESSIBILITY = 1 << 1, +} ArkUI_AccessibilityFocusType; + +/** + * @brief Enumerates the API accessibility focus move direction. + * + * @since 13 + * @version 1.0 + */ +typedef enum { + /** Invalid */ + NATIVE_DIRECTION_INVALID = 0, + /** up direction. */ + NATIVE_DIRECTION_UP = 0x00000001, + /** down direction. */ + NATIVE_DIRECTION_DOWN = 0x00000002, + /** left direction. */ + NATIVE_DIRECTION_LEFT = 0x00000004, + /** right direction. */ + NATIVE_DIRECTION_RIGHT = 0x00000008, + /** forward direction. */ + NATIVE_DIRECTION_FORWARD = 0x00000010, + /** backward direction. */ + NATIVE_DIRECTION_BACKWARD = 0x00000020, +} ArkUI_AccessibilityFocusMoveDirection; + +/** + * @brief Provides an encapsulated ArkUI_AccessibilityElementInfoList instance. + * + * @since 13 + * @version 1.0 + */ +typedef struct ArkUI_AccessibilityElementInfoList ArkUI_AccessibilityElementInfoList; + +/** + * @brief Registers the accessibility provider callbacks + * + * @since 13 + * @version 1.0 + */ +typedef struct ArkUI_AccessibilityProviderCallbacks { + /** Called when need to get element infos based on a specified node. */ + int32_t (*FindAccessibilityNodeInfosById)(int64_t elementId, ArkUI_AccessibilitySearchMode mode, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList); + /** Called when need to get element infos based on a specified node and text content. */ + int32_t (*FindAccessibilityNodeInfosByText)(int64_t elementId, const char* text, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList); + /** Called when need to get the focused element info based on a specified node. */ + int32_t (*FindFocusedAccessibilityNode)(int64_t elementId, ArkUI_AccessibilityFocusType focusType, int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo); + /** Query the node that can be focused based on the reference node. Query the next node that can be focused based on the mode and direction. */ + int32_t (*FindNextFocusAccessibilityNode)(int64_t elementId, ArkUI_AccessibilityFocusMoveDirection direction, int32_t requestId, ArkUI_AccessibilityElementInfo* elementList); + /** Performing the Action operation on a specified node. */ + int32_t (*ExecuteAccessibilityAction)(int64_t elementId, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments actionArguments, int32_t requestId); + /** Clears the focus status of the currently focused node */ + int32_t (*ClearFocusedFocusAccessibilityNode)(); + /** Queries the current cursor position of a specified node. */ + int32_t (*GetAccessibilityNodeCursorPosition)(int64_t elementId, int32_t requestId, int32_t* index); +} ArkUI_AccessibilityProviderCallbacks; + +/** + * @brief Registers a callback for this ArkUI_AccessibilityProvider instance. + * + * @param provider Indicates the pointer to this ArkUI_AccessibilityProvider instance. + * @param callbacks Indicates the pointer to a GetAccessibilityNodeCursorPosition callback. + * @return Returns the status code of the execution. + * @since 13 + * @version 1.0 + */ +int32_t OH_ArkUI_AccessibilityProviderRegisterCallback( + ArkUI_AccessibilityProvider* provider, ArkUI_AccessibilityProviderCallbacks* callbacks); + +/** + * @brief send accessibility event info. + * + * @param provider Indicates the pointer to this ArkUI_AccessibilityProvider instance. + * @param eventInfo Indicates the pointer to the accessibility event info. + * @param callback Indicates the pointer to a SendAccessibilityAsyncEvent callback. + * @return Returns the status code of the execution. + * @since 13 + * @version 1.0 + */ +void OH_ArkUI_SendAccessibilityAsyncEvent( + ArkUI_AccessibilityProvider* provider, ArkUI_AccessibilityEventInfo* eventInfo, void (*callback)(int32_t errorCode)); + +/** + * @brief Adds an element to the list. + * + * @param list Indicates the pointer to the accessibility element list. + * @return Returns the pointer to the accessibility elementInfo. + * @since 13 + * @version 1.0 + */ +ArkUI_AccessibilityElementInfo* OH_ArkUI_AddAndGetAccessibilityElementInfo(ArkUI_AccessibilityElementInfoList* list); + +/** +* @brief Sets the page id of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param pageId Indicates the page id. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoPageId(ArkUI_AccessibilityElementInfo* elementInfo, int32_t pageId); + +/** +* @brief Sets the page id of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param componentId Indicates the component id. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoComponentId(ArkUI_AccessibilityElementInfo* elementInfo, int32_t componentId); + +/** +* @brief Sets the parent id of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param parentId Indicates the parent id. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoParentId(ArkUI_AccessibilityElementInfo* elementInfo, int32_t parentId); + +/** +* @brief Sets the component type of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param componentType Indicates the component type. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoComponentType(ArkUI_AccessibilityElementInfo* elementInfo, const char* componentType); + +/** +* @brief Sets the component contents of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param contents Indicates the component contents. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoContents(ArkUI_AccessibilityElementInfo* elementInfo, const char* contents); + +/** +* @brief Sets the hint text of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param hintText Indicates the hint text. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoHintText(ArkUI_AccessibilityElementInfo* elementInfo, const char* hintText); + +/** +* @brief Sets the accessibility text of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param accessibilityText Indicates the accessibility text. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoAccessibilityText(ArkUI_AccessibilityElementInfo* elementInfo, const char* accessibilityText); + +/** +* @brief Sets the accessibility description of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param accessibilityDescription Indicates the accessibility description. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoAccessibilityDescription(ArkUI_AccessibilityElementInfo* elementInfo, const char* accessibilityDescription); + +/** +* @brief Sets the child node ids of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param childCount Indicates the child count. +* @param childNodeIds Indicates the child node ids. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoChildNodeIds(ArkUI_AccessibilityElementInfo* elementInfo, int32_t childCount, int64_t* childNodeIds); + +/** +* @brief Sets the child count of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param operationActions Indicates All actions supported by the element. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoOperationActions(ArkUI_AccessibilityElementInfo* elementInfo, int32_t operationCount, ArkUI_AccessibleAction* operationActions); + +/** +* @brief Sets the screen rect of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param screenRect Indicates screen rect. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoScreenRect(ArkUI_AccessibilityElementInfo* elementInfo, ArkUI_AccessibleRect* screenRect); + +/** +* @brief Sets the checkable of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param checkable Indicates checkable. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoCheckable(ArkUI_AccessibilityElementInfo* elementInfo, bool checkable); + +/** +* @brief Sets the checked of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param checked Indicates whether the element is checked. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoChecked(ArkUI_AccessibilityElementInfo* elementInfo, bool checked); + +/** +* @brief Sets the focusable of the accessibility element information. +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param focusable Indicates whether the element is focusable. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoFocusable(ArkUI_AccessibilityElementInfo* elementInfo, bool focusable); + +/** +* @brief Sets the isFocused of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param isFocused Indicates whether the element is focused. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoFocused(ArkUI_AccessibilityElementInfo* elementInfo, bool isFocused); + +/** +* @brief Sets the isVisible of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param isVisible Indicates whether the element is visible. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoVisible(ArkUI_AccessibilityElementInfo* elementInfo, bool isVisible); + +/** +* @brief Sets the accessibilityFocused of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param accessibilityFocused Indicates whether the element is accessibility focused. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoAccessibilityFocused(ArkUI_AccessibilityElementInfo* elementInfo, bool accessibilityFocused); + +/** +* @brief Sets the selected of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param selected Indicates whether the element is selected. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoSelected(ArkUI_AccessibilityElementInfo* elementInfo, bool selected); + +/** +* @brief Sets the clickable of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param clickable Indicates whether the element is clickable. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoClickable(ArkUI_AccessibilityElementInfo* elementInfo, bool clickable); + +/** +* @brief Sets the longClickable of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param longClickable Indicates whether the element is long clickable. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoLongClickable(ArkUI_AccessibilityElementInfo* elementInfo, bool longClickable); + +/** +* @brief Sets the isEnabled of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param isEnable Indicates whether the element is enable. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoEnabled(ArkUI_AccessibilityElementInfo* elementInfo, bool isEnabled); + +/** +* @brief Sets the isPassword of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param isPassword Indicates whether the element is a password. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoIsPassword(ArkUI_AccessibilityElementInfo* elementInfo, bool isPassword); + +/** +* @brief Sets the scrollable of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param scrollable Indicates whether the element is scrollable. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoScrollable(ArkUI_AccessibilityElementInfo* elementInfo, bool scrollable); + +/** +* @brief Sets the editable of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param editable Indicates whether the element is editable. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoEditable(ArkUI_AccessibilityElementInfo* elementInfo, bool editable); + +/** +* @brief Sets the isHint of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param isHint Indicates whether the element is in the hint state. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoIsHint(ArkUI_AccessibilityElementInfo* elementInfo, bool isHint); + +/** +* @brief Sets the rangeInfo of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param rangeInfo Indicates element's range info. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoRangeInfo(ArkUI_AccessibilityElementInfo* elementInfo, ArkUI_AccessibleRangeInfo* rangeInfo); + +/** +* @brief Sets the grid of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param gridInfo Indicates element's grid info. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoGridInfo(ArkUI_AccessibilityElementInfo* elementInfo, ArkUI_AccessibleGridInfo* gridInfo); + +/** +* @brief Sets the gridItem of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param gridItem Indicates element's grid item info. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoGridItemInfo(ArkUI_AccessibilityElementInfo* elementInfo, ArkUI_AccessibleGridItemInfo* gridItem); + +/** +* @brief Sets the textBeginSelected of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param textBeginSelected Indicates the start position of the selection. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoTextBeginSelected(ArkUI_AccessibilityElementInfo* elementInfo, int32_t textBeginSelected); + +/** +* @brief Sets the textEndSelected of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param textEndSelected Indicates the end position of the selection. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoTextEndSelected(ArkUI_AccessibilityElementInfo* elementInfo, int32_t textEndSelected); + +/** +* @brief Sets the currentItemIndex of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param currentItemIndex Indicates index of the current item. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoCurrentItemIndex(ArkUI_AccessibilityElementInfo* elementInfo, int32_t currentItemIndex); + +/** +* @brief Sets the beginItemIndex of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param beginItemIndex Indicates index of the begin item. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoBeginItemIndex(ArkUI_AccessibilityElementInfo* elementInfo, int32_t beginItemIndex); + +/** +* @brief Sets the endItemIndex of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param endItemIndex Indicates index of the end item. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoEndItemIndex(ArkUI_AccessibilityElementInfo* elementInfo, int32_t endItemIndex); + +/** +* @brief Sets the itemCount of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param itemCount Indicates total number of items. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoItemCount(ArkUI_AccessibilityElementInfo* elementInfo, int32_t itemCount); + +/** +* @brief Sets the offset of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param offset Indicates pixel offset for scrolling relative to the top coordinate of the element. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoAccessibilityOffset(ArkUI_AccessibilityElementInfo* elementInfo, int32_t offset); + +/** +* @brief Sets the accessibilityGroup of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param accessibilityGroup Indicates accessibility group. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoAccessibilityGroup(ArkUI_AccessibilityElementInfo* elementInfo, bool accessibilityGroup); + +/** +* @brief Sets the accessibilityLevel of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param accessibilityLevel Indicates accessibility level. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoAccessibilityLevel(ArkUI_AccessibilityElementInfo* elementInfo, const char* accessibilityLevel); + +/** +* @brief Sets the zIndex of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param zIndex Indicates z index. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoZIndex(ArkUI_AccessibilityElementInfo* elementInfo, int32_t zIndex); + +/** +* @brief Sets the opacity of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param opacity Indicates opacity. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoAccessibilityOpacity(ArkUI_AccessibilityElementInfo* elementInfo, float opacity); + +/** +* @brief Sets the backgroundColor of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param backgroundColor Indicates background color. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoBackgroundColor(ArkUI_AccessibilityElementInfo* elementInfo, const char* backgroundColor); + +/** +* @brief Sets the backgroundImage of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param backgroundImage Indicates background image. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoBackgroundImage(ArkUI_AccessibilityElementInfo* elementInfo, const char* backgroundImage); + +/** +* @brief Sets the blur of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param blur Indicates blur. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoBlur(ArkUI_AccessibilityElementInfo* elementInfo, const char* blur); + +/** +* @brief Sets the hitTestBehavior of the accessibility element information. +* +* @param elementInfo Indicates the pointer to the accessibility element information. +* @param hitTestBehavior Indicates hitTest behavior. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityElementInfoHitTestBehavior(ArkUI_AccessibilityElementInfo* elementInfo, const char* hitTestBehavior); + +/** + * @brief Create an accessibility eventInfo. + * + * @return Returns the pointer to the accessibility event info. + * @since 13 + * @version 1.0 + */ +ArkUI_AccessibilityEventInfo* OH_ArkUI_CreateAccessibilityEventInfo(void); + +/** + * @brief Destorys an accessibility eventInfo. + * + * @param eventInfo Indicates the pointer to to the accessibility event info to be destoryed. + * @since 13 + * @version 1.0 + */ +void OH_ArkUI_DestoryAccessibilityEventInfo(ArkUI_AccessibilityEventInfo* eventInfo); + +/** +* @brief Sets the eventType of the accessibility event information. +* +* @param eventInfo Indicates the pointer to the accessibility event information. +* @param eventType Indicates event type. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityEventEventType(ArkUI_AccessibilityEventInfo* eventInfo, ArkUI_AccessibilityEventType eventType); + +/** +* @brief Sets the pageId of the accessibility event information. +* +* @param eventInfo Indicates the pointer to the accessibility event information. +* @param pageId Indicates page id. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityEventPageId(ArkUI_AccessibilityEventInfo* eventInfo, int32_t pageId); + +/** +* @brief Sets the textAnnouncedForAccessibility of the accessibility event information. +* +* @param eventInfo Indicates the pointer to the accessibility event information. +* @param textAnnouncedForAccessibility Indicates text announced for accessibility. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityEventTextAnnouncedForAccessibility(ArkUI_AccessibilityEventInfo* eventInfo, const char* textAnnouncedForAccessibility); + +/** +* @brief Sets the requestFocusId of the accessibility event information. +* +* @param eventInfo Indicates the pointer to the accessibility event information. +* @param requestFocusId Indicates ID of the request for active focus. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityEventRequestFocusId(ArkUI_AccessibilityEventInfo* eventInfo, int32_t requestFocusId); + +/** +* @brief Sets the elementInfo of the accessibility event information. +* +* @param eventInfo Indicates the pointer to the accessibility event information. +* @param elementInfo Indicates element Info. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_SetAccessibilityEventElementInfo(ArkUI_AccessibilityEventInfo* eventInfo, ArkUI_AccessibilityElementInfo* elementInfo); + +/** +* @brief Gets the value of the accessibility action argument by key. +* +* @param arguments Indicates the pointer to the accessibility action arguments. +* @param key Indicates key. +* @param value Indicates value. +* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. +* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. +* @since 13 +*/ +int32_t OH_ArkUI_FindAccessibilityActionArgumentByKey(ArkUI_AccessibilityActionArguments* arguments, const char* key, char* value); +#ifdef __cplusplus +}; +#endif +#endif // _NATIVE_INTERFACE_ACCESSIBILITY_H diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 83d8096080..33f705c271 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -23,24 +23,181 @@ namespace flutter { OhosAccessibilityBridge::OhosAccessibilityBridge() = default; OhosAccessibilityBridge::~OhosAccessibilityBridge() = default; -void OhosAccessibilityBridge::updateSemantics( // TODO debug sending test - std::vector buffer, - std::vector strings, - std::vector> string_attribute_args) { - FML_DLOG(INFO) << "buffer size: " << buffer.size() - << "strings size: " << strings.size() - << "string_attribute_args size: " << string_attribute_args.size(); +flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateSemanticsNode( + int32_t id) { + flutter::SemanticsNode node; + if (flutterSemanticsTree_.find(id) != flutterSemanticsTree_.end()) { + node = flutterSemanticsTree_.at(id); + } else { + flutterSemanticsTree_[id] = node; + } + return node; +} + +void OhosAccessibilityBridge::updateSemantics( + flutter::SemanticsNodeUpdates update, + flutter::CustomAccessibilityActionUpdates actions) { FML_DLOG(INFO) << ("Native C++ OhosAccessibilityBridge::updateSemantics"); + + // 遍历更新的actions,并将所有的actions的id添加进actionMap + for (const auto& item : actions) { + const flutter::CustomAccessibilityAction action = item.second; + actions_mp_[action.id] = action; + } + + for (auto& item : update) { + const flutter::SemanticsNode& node = item.second; + // todo:根据nodeId获取当前os对应的真实节点 + // currentNode = + // ArkUI_AccessibilityElementInfo::createAccessibilityElementInfo(node.id); + + // todo:获取当前节点的全部子节点数量,并构建当前节点的全部更新子节点 + int32_t newChildCount = node.childrenInTraversalOrder.size(); + // todo:声明并创建当前节点的新的子节点 + // declare一个newChildren + for (int32_t i = 0; i < newChildCount; i++) { + // todo:通过遍历当前节点的子节点,并对所有子节点进行逐一构建os对应的elementinfo + // AccessibilityElementInfo child = + // createAccessibilityElementInfo(node.childrenInTraversalOrder[i]); + // todo:将所有的新child节点加入到os对应的elementInfoList中 + } + // TODO: 将更新后的全部子节点赋值给当前真实节点 + // currentNode = newChildren + + // todo: 是否触发滑动操作 + bool didScroll = true; + if (didScroll) { + // 1. 声明并创建accessibilityEvent类型,比如滑动事件 + // 2. + // 获取semanticsNode里scrollPosition、scrollExtensionMax、scrollExtensionMin字段 + // 3. 发送事件中包含上述scroll位置变动信息(如下所示) + // int32_t scrollChildren = 0; + // int32_t scrollIndex = 0; + // double scrollPosition = std::nan(""); + // double scrollExtentMax = std::nan(""); + // double scrollExtentMin = std::nan(""); + int32_t scrollChildren = 0; + if (scrollChildren > 0) { + // todo 发送事件,包含scrollChildren数量、scrollIndex + // int visibleChildren = 0; + // // handle hidden children at the beginning and end of the list. + // for (flutter::SemanticsNode child : node.childrenInHitTestOrder) { + // if (!child.hasFlag(Flag.IS_HIDDEN)) { + // visibleChildren += 1; + // } + // } + } + // sendAccessibilityEvent(event) + } + // todo: 判断是否触发liveRegion活动区,是否活跃 + if(node.HasFlag(FLAGS_::kIsLiveRegion)) { + // sendWindowContentChangeEvent(object.id); + } + + //todo:当前焦点语义节点 + bool isHadFlag = false; //这里判断previousFlag和当前flag是否相同 + std::shared_ptr accessibilityFocusedSemanticsNode; + if (accessibilityFocusedSemanticsNode != nullptr + && accessibilityFocusedSemanticsNode->id == node.id + && !isHadFlag + && node.HasFlag(FLAGS_::kIsSelected)) { + // todo:创建并发送事件 + // AccessibilityEvent event = obtainAccessibilityEvent( + // node.id, AccessibilityEvent.TYPE_VIEW_SELECTED); + // event.getText().add(object.label); + // sendAccessibilityEvent(event); + } + + //todo: 若该对象是输入焦点节点,且发生更新变化,则发送给os有关它的信息 + std::shared_ptr inputFocusedSemanticsNode; //当前输入焦点节点 + std::shared_ptr lastInputFocusedSemanticsNode; //上一个输入焦点节点 + if (inputFocusedSemanticsNode != nullptr + && inputFocusedSemanticsNode->id == node.id + && (lastInputFocusedSemanticsNode == nullptr + || lastInputFocusedSemanticsNode->id != inputFocusedSemanticsNode->id)) { + // 上次输入焦点节点 -> 当前输入焦点节点 + lastInputFocusedSemanticsNode = inputFocusedSemanticsNode; + // 发送相应的输入焦点改变事件 + // sendAccessibilityEvent(obtainAccessibilityEvent(object.id, + // AccessibilityEvent.TYPE_VIEW_FOCUSED)); + } else if (inputFocusedSemanticsNode == nullptr) { + // There's no TYPE_VIEW_CLEAR_FOCUSED event, so if the current input focus + // becomes null, then we just set the last one to null too, so that it + // sends the event again when something regains focus. + lastInputFocusedSemanticsNode = nullptr; + } + + if (inputFocusedSemanticsNode != nullptr + && inputFocusedSemanticsNode->id == node.id + && isHadFlag + && node.HasFlag(FLAGS_::kIsTextField) + // If we have a TextField that has InputFocus, we should avoid announcing it if something + // else we track has a11y focus. This needs to still work when, e.g., IME has a11y focus + // or the "PASTE" popup is used though. + // See more discussion at https://github.com/flutter/flutter/issues/23180 + && (accessibilityFocusedSemanticsNode == nullptr + || (accessibilityFocusedSemanticsNode->id == inputFocusedSemanticsNode->id))) { + // 这里写输入框更新文字内容,将老旧的文本替换为新输入文字,并发送textchange事件 + // AccessibilityEvent event = createTextChangedEvent(object.id, oldValue, + // newValue); sendAccessibilityEvent(event); + + // todo:若当前textselection部分和之前的textselection部分不同,则触发 + int32_t previousTextSelectionBase = 0; + int32_t previousTextSelectionExtent = 1; + if (previousTextSelectionBase != node.textSelectionBase || + previousTextSelectionExtent != node.textSelectionExtent) { + // 创建并发送textselection改变事件 + // AccessibilityEvent selectionEvent = obtainAccessibilityEvent( + // object.id, AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); + // selectionEvent.getText().add(newValue); + // selectionEvent.setFromIndex(object.textSelectionBase); + // selectionEvent.setToIndex(object.textSelectionExtent); + // selectionEvent.setItemCount(newValue.length()); + // sendAccessibilityEvent(selectionEvent); + } + } + } +} + +void OhosAccessibilityBridge::performAction(int32_t virtualViewId, + int32_t inputAction) { + // TODO 根据输入的action进行相应的响应操作 + switch (inputAction) { + case 0: + break; + case 1: + break; + case 2: + break; + // ... + default: + break; + } +} + +flutter::SemanticsNode OhosAccessibilityBridge::getRootSemanticsNode() { + return flutterSemanticsTree_.at(0); +} +// 找到当前焦点触发节点 +int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( + int64_t elementId, + int32_t focusType, + int32_t requestId, + int32_t elementinfo) { + return 0; +} +// 找到下一个焦点触发节点 +int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( + int64_t elementId, + int32_t direction, + int32_t requestId, + int32_t elementList) { + return 0; } -void OhosAccessibilityBridge::updateCustomAccessibilityActions( - std::vector buffer, - std::vector strings) { - FML_DLOG(INFO) << "buffer size: " << buffer.size() - << "strings size: " << strings.size(); - FML_DLOG(INFO) - << ("Native C++ " - "OhosAccessibilityBridge::updateCustomAccessibilityActions"); +void ArkUI_AccessibilityElementInfo::createAccessibilityElementInfo(int vid) { + // TODO ohos和flutter虚拟节点交互,根据虚拟节点id创建真实elementinfo + // ArkUI_AccessibilityElementInfo相当于安卓的view } } // namespace flutter diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 925a202748..57ccc87f9f 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -15,34 +15,141 @@ #ifndef OHOS_ACCESSIBILITY_BRIDGE_H #define OHOS_ACCESSIBILITY_BRIDGE_H - -#include "flutter/fml/log_level.h" -// #include "flutter/fml/macros.h" -#include "flutter/lib/ui/semantics/semantics_node.h" #include #include #include #include -namespace flutter { +#include "flutter/fml/log_level.h" +// #include "flutter/fml/macros.h" +#include "flutter/lib/ui/semantics/semantics_node.h" +// #include "flutter/shell/platform/common/accessibility_bridge.h" +#include "flutter/lib/ui/semantics/custom_accessibility_action.h" +// #include "flutter/shell/platform/ohos/accessibility/native_interface_accessibility.h" +namespace flutter { +typedef flutter::SemanticsFlags FLAGS_; /** * flutter和ohos的无障碍服务桥接 */ -class OhosAccessibilityBridge { +class OhosAccessibilityBridge { public: OhosAccessibilityBridge(); ~OhosAccessibilityBridge(); - void updateSemantics(std::vector buffer, - std::vector strings, - std::vector> string_attribute_args); + void updateSemantics(flutter::SemanticsNodeUpdates update, + flutter::CustomAccessibilityActionUpdates actions); + // obtain the flutter semnatics node + flutter::SemanticsNode getOrCreateSemanticsNode(int32_t id); - void updateCustomAccessibilityActions(std::vector buffer, - std::vector strings); + void performAction(int32_t virtualViewId, int32_t inputAction); private: - std::unordered_map flutterSemanticsTree; + std::unordered_map flutterSemanticsTree_; + std::unordered_map actions_mp_; + + flutter::SemanticsNode semanticsNode_; + // flutter::SemanticsFlags flags_; + + flutter::SemanticsNode getRootSemanticsNode(); + + // native os interfaces + int32_t FindFocusedAccessibilityNode(int64_t elementId, + int32_t focusType, + int32_t requestId, + int32_t elementinfo); + int32_t FindNextFocusAccessibilityNode(int64_t elementId, + int32_t direction, + int32_t requestId, + int32_t elementList); +}; + +class ArkUI_AccessibilityElementInfo { + public: + ArkUI_AccessibilityElementInfo() = default; + ~ArkUI_AccessibilityElementInfo() = default; + void createAccessibilityElementInfo(int vid); +}; +/** +struct SemanticsNode { + SemanticsNode(); + + SemanticsNode(const SemanticsNode& other); + + ~SemanticsNode(); + + bool HasAction(SemanticsAction action) const; + bool HasFlag(SemanticsFlags flag) const; + + // Whether this node is for embedded platform views. + bool IsPlatformViewNode() const; + + int32_t id = 0; + int32_t flags = 0; + int32_t actions = 0; + int32_t maxValueLength = -1; + int32_t currentValueLength = -1; + int32_t textSelectionBase = -1; + int32_t textSelectionExtent = -1; + int32_t platformViewId = -1; + int32_t scrollChildren = 0; + int32_t scrollIndex = 0; + double scrollPosition = std::nan(""); + double scrollExtentMax = std::nan(""); + double scrollExtentMin = std::nan(""); + double elevation = 0.0; + double thickness = 0.0; + std::string label; + StringAttributes labelAttributes; + std::string hint; + StringAttributes hintAttributes; + std::string value; + StringAttributes valueAttributes; + std::string increasedValue; + StringAttributes increasedValueAttributes; + std::string decreasedValue; + StringAttributes decreasedValueAttributes; + std::string tooltip; + int32_t textDirection = 0; // 0=unknown, 1=rtl, 2=ltr + + SkRect rect = SkRect::MakeEmpty(); // Local space, relative to parent. + SkM44 transform = SkM44{}; // Identity + std::vector childrenInTraversalOrder; + std::vector childrenInHitTestOrder; + std::vector customAccessibilityActions; }; +*/ + +/** + enum class SemanticsFlags : int32_t { + kHasCheckedState = 1 << 0, + kIsChecked = 1 << 1, + kIsSelected = 1 << 2, + kIsButton = 1 << 3, + kIsTextField = 1 << 4, + kIsFocused = 1 << 5, + kHasEnabledState = 1 << 6, + kIsEnabled = 1 << 7, + kIsInMutuallyExclusiveGroup = 1 << 8, + kIsHeader = 1 << 9, + kIsObscured = 1 << 10, + kScopesRoute = 1 << 11, + kNamesRoute = 1 << 12, + kIsHidden = 1 << 13, + kIsImage = 1 << 14, + kIsLiveRegion = 1 << 15, + kHasToggledState = 1 << 16, + kIsToggled = 1 << 17, + kHasImplicitScrolling = 1 << 18, + kIsMultiline = 1 << 19, + kIsReadOnly = 1 << 20, + kIsFocusable = 1 << 21, + kIsLink = 1 << 22, + kIsSlider = 1 << 23, + kIsKeyboardKey = 1 << 24, + kIsCheckStateMixed = 1 << 25, +}; + */ + } // namespace flutter #endif // OHOS_ACCESSIBILITY_BRIDGE_H diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets index cf4729c183..dfa943f2ad 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets @@ -137,3 +137,8 @@ export const nativeRegisterTexture: (nativeShellHolderId: number, textureId: num export const nativeEncodeUtf8: (str: string) => Uint8Array; export const nativeDecodeUtf8: (array: Uint8Array) => string; + +/** + * accessibiltyChannel中的 + */ +export const nativeSetAccessibilityFeatures: (accessibilityFeatureFlags: number, responseId: number) => void; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index 88fe03d2a0..089f3c7e6e 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -331,7 +331,8 @@ export default class FlutterNapi { setAccessibilityFeatures(accessibilityFeatureFlags: number, responseId: number): void { if (this.isAttached()) { - this.nativeSetAccessibilityFeatures(accessibilityFeatureFlags, responseId); + // this.nativeSetAccessibilityFeatures(accessibilityFeatureFlags, responseId); + flutter.nativeSetAccessibilityFeatures(accessibilityFeatureFlags, responseId); } else { Log.w( TAG, @@ -344,7 +345,8 @@ export default class FlutterNapi { dispatchSemanticsAction(virtualViewId: number, action: Action, responseId: number): void { if (this.isAttached()) { - this.nativeDispatchSemanticsAction(virtualViewId, action, responseId); + // this.nativeDispatchSemanticsAction(virtualViewId, action, responseId); + // flutter. } else { Log.w( TAG, diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index 4331e5f271..0509472ed8 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -297,7 +297,9 @@ void PlatformViewOHOS::UpdateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { FML_DLOG(INFO) << "PlatformViewOHOS::UpdateSemantics"; - platform_view_ohos_delegate_->UpdateSemantics(update, actions); + // platform_view_ohos_delegate_->UpdateSemantics(update, actions); + ax_bridge_delegate_->updateSemantics(update, actions); + } // |PlatformView| diff --git a/shell/platform/ohos/platform_view_ohos.h b/shell/platform/ohos/platform_view_ohos.h index 512efeb78a..56916b705c 100644 --- a/shell/platform/ohos/platform_view_ohos.h +++ b/shell/platform/ohos/platform_view_ohos.h @@ -36,6 +36,7 @@ #include "flutter/shell/platform/ohos/surface/ohos_surface.h" #include "flutter/shell/platform/ohos/vsync_waiter_ohos.h" #include "flutter/shell/platform/ohos/platform_view_ohos_delegate.h" +#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" namespace flutter { @@ -141,6 +142,7 @@ class PlatformViewOHOS final : public PlatformView { std::map contextDatas_; std::shared_ptr platform_view_ohos_delegate_; + std::shared_ptr ax_bridge_delegate_; static bool isDestroyed_; static pthread_mutex_t mutex_; diff --git a/shell/platform/ohos/platform_view_ohos_delegate.cpp b/shell/platform/ohos/platform_view_ohos_delegate.cpp index 946ebd79c9..16527e0385 100644 --- a/shell/platform/ohos/platform_view_ohos_delegate.cpp +++ b/shell/platform/ohos/platform_view_ohos_delegate.cpp @@ -46,7 +46,7 @@ void putStringAttributesIntoBuffer( } } } - +// interaction between java and native, encoding the semantics info to bytebuffer PlatformViewOHOSDelegate::PlatformViewOHOSDelegate( std::shared_ptr napi_facade) : napi_facade_(std::move(napi_facade)) {}; @@ -214,8 +214,8 @@ void PlatformViewOHOSDelegate::UpdateSemantics( if (!actions_buffer.empty()) { // napi_facade_->FlutterViewUpdateCustomAccessibilityActions(actions_buffer, // action_strings); - ax_bridge_router_->updateCustomAccessibilityActions(actions_buffer, - action_strings); + // ax_bridge_router_->updateCustomAccessibilityActions(actions_buffer, + // action_strings); FML_DLOG(INFO) << "PlatformViewOHOSDelegate::" "updateCustomAccessibilityActions is called"; } @@ -223,8 +223,8 @@ void PlatformViewOHOSDelegate::UpdateSemantics( if (!buffer.empty()) { // napi_facade_->FlutterViewUpdateSemantics(buffer, strings, // string_attribute_args); - ax_bridge_router_->updateSemantics(buffer, strings, - string_attribute_args); + // ax_bridge_router_->updateSemantics(buffer, strings, + // string_attribute_args); FML_DLOG(INFO) << "PlatformViewOHOSDelegate::UpdateSemantics is called"; } } -- Gitee From 88ef19896135752cd8d4749f0cb475676c28d5b7 Mon Sep 17 00:00:00 2001 From: liujiake Date: Fri, 30 Aug 2024 14:31:50 +0800 Subject: [PATCH 004/151] add nativeAccessibilityStateChange interface Signed-off-by: liujiake --- .../src/main/cpp/types/libflutter/index.d.ets | 2 ++ .../src/main/ets/embedding/engine/FlutterNapi.ets | 10 ++++++++++ .../src/main/ets/view/AccessibilityBridge.ets | 4 ++++ .../flutter/src/main/ets/view/FlutterView.ets | 8 ++++++++ shell/platform/ohos/library_loader.cpp | 3 +++ .../platform/ohos/napi/platform_view_ohos_napi.cpp | 13 +++++++++++++ shell/platform/ohos/napi/platform_view_ohos_napi.h | 3 +++ 7 files changed, 43 insertions(+) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets index dfa943f2ad..992a4e64d0 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets @@ -142,3 +142,5 @@ export const nativeDecodeUtf8: (array: Uint8Array) => string; * accessibiltyChannel中的 */ export const nativeSetAccessibilityFeatures: (accessibilityFeatureFlags: number, responseId: number) => void; + +export const nativeAccessibilityStateChange: (state: Boolean) => string; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index 089f3c7e6e..38f3de9ebc 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -390,6 +390,14 @@ export default class FlutterNapi { flutter.nativeUpdateCustomAccessibilityActions(buffer, strings); } + accessibilityStateChange(state: Boolean): void { + this.ensureRunningOnMainThread(); + if(this.accessibilityDelegate != null) { + this.accessibilityDelegate.accessibilityStateChange(state); + } + Log.d(TAG, "accessibilityStateChange is called"); + flutter.nativeAccessibilityStateChange(state); + } setLocalizationPlugin(localizationPlugin: LocalizationPlugin | null): void { this.localizationPlugin = localizationPlugin; @@ -519,4 +527,6 @@ export interface AccessibilityDelegate { updateCustomAccessibilityActions(buffer: ByteBuffer, strings: string[]): void; updateSemantics(buffer: ByteBuffer, strings: string[], stringAttributeArgs: ByteBuffer[]): void; + + accessibilityStateChange(state: Boolean): void; } diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets index 015d195d7d..1cfc8a801a 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets @@ -64,6 +64,10 @@ export default class AccessibilityBridge implements AccessibilityMessageHandler } + accessibilityStateChange(state: Boolean): void{ + Log.d(TAG, "AccessibilityBridge.ets accessibilityStateChange is called"); + } + /** * TODO lack of AccessibilityManager.AccessibilityStateChangeListener * Listener that is notified when accessibility is turned on/off. diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index 03bdbc5b08..e646144729 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -26,6 +26,7 @@ import ArrayList from '@ohos.util.ArrayList'; import { EmbeddingNodeController } from '../embedding/ohos/EmbeddingNodeController'; import PlatformView, { Params } from '../plugin/platform/PlatformView'; import { JSON } from '@kit.ArkTS'; +import { accessibility } from '@kit.AccessibilityKit'; const TAG = "FlutterViewTag"; @@ -106,6 +107,10 @@ export class FlutterView { this.mainWindow?.on('windowSizeChange', this.windowSizeChangeCallback); this.mainWindow?.on('avoidAreaChange', this.avoidAreaChangeCallback); this.mainWindow?.on('windowStatusChange', this.windowStatusChangeCallback); + accessibility.on('accessibilityStateChange', (data: boolean) => { + Log.i(TAG, `subscribe accessibility state change, result: ${JSON.stringify(data)}`); + this.flutterEngine?.getFlutterNapi()?.accessibilityStateChange(data); + }); } private windowSizeChangeCallback = (data: window.Size) => { @@ -174,6 +179,9 @@ export class FlutterView { this.mainWindow?.off('windowSizeChange', this.windowSizeChangeCallback); this.mainWindow?.off('avoidAreaChange', this.avoidAreaChangeCallback); this.mainWindow?.off('windowStatusChange', this.windowStatusChangeCallback); + accessibility.off('accessibilityStateChange', (data: boolean) => { + Log.i(TAG, `unsubscribe accessibility state change, result: ${JSON.stringify(data)}`); + }); } catch (e) { Log.e(TAG, "mainWindow off error: " + JSON.stringify(e)); } diff --git a/shell/platform/ohos/library_loader.cpp b/shell/platform/ohos/library_loader.cpp index 26e8007afd..1c71193f23 100644 --- a/shell/platform/ohos/library_loader.cpp +++ b/shell/platform/ohos/library_loader.cpp @@ -139,6 +139,9 @@ static napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_FUNCTION( "nativeUpdateCustomAccessibilityActions", flutter::PlatformViewOHOSNapi::nativeUpdateCustomAccessibilityActions), + DECLARE_NAPI_FUNCTION( + "nativeAccessibilityStateChange", + flutter::PlatformViewOHOSNapi::nativeAccessibilityStateChange), }; diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index 9de18c094d..28ba0ade26 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1819,4 +1819,17 @@ napi_value PlatformViewOHOSNapi::nativeUpdateCustomAccessibilityActions( return nullptr; } +napi_value PlatformViewOHOSNapi::nativeAccessibilityStateChange( + napi_env env, + napi_callback_info info) { + size_t argc = 1; + napi_value args[1] = {nullptr}; + LOGD("PlatformViewOHOSNapi::nativeAccessibilityStateChange"); + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + bool state = false; + napi_get_value_bool(env, args[0], &state); + LOGD("PlatformViewOHOSNapi::nativeAccessibilityStateChange state is: %{public}s", (state ? "ture" : "false")); + return nullptr; +} + } // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h index 3e54845081..45dcb187d2 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.h +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -202,6 +202,9 @@ class PlatformViewOHOSNapi { static napi_value nativeUpdateCustomAccessibilityActions( napi_env env, napi_callback_info info); + static napi_value nativeAccessibilityStateChange( + napi_env env, + napi_callback_info info); private: static napi_env env_; -- Gitee From 1a4a6767963e024274fee951dc672aa744d2dbd8 Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 30 Aug 2024 16:07:26 +0800 Subject: [PATCH 005/151] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E9=83=A8?= =?UTF-8?q?=E5=88=86=E4=BB=A3=E7=A0=81=E7=9A=84debug=E6=89=93=E5=8D=B0?= =?UTF-8?q?=E8=B0=83=E8=AF=95=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- lib/ui/window/platform_configuration.cc | 19 ++-- runtime/runtime_controller.cc | 3 + .../ohos_accessibility_bridge.cpp | 91 ++++++++++++------- .../accessibility/ohos_accessibility_bridge.h | 31 +++++++ .../systemchannels/AccessibilityChannel.ets | 5 +- 5 files changed, 108 insertions(+), 41 deletions(-) diff --git a/lib/ui/window/platform_configuration.cc b/lib/ui/window/platform_configuration.cc index 296847f9aa..cdd348a5dd 100644 --- a/lib/ui/window/platform_configuration.cc +++ b/lib/ui/window/platform_configuration.cc @@ -6,13 +6,13 @@ #include +#include "flutter/fml/trace_event.h" #include "flutter/lib/ui/compositing/scene.h" #include "flutter/lib/ui/ui_dart_state.h" #include "flutter/lib/ui/window/platform_message_response_dart.h" #include "flutter/lib/ui/window/platform_message_response_dart_port.h" #include "flutter/lib/ui/window/viewport_metrics.h" #include "flutter/lib/ui/window/window.h" -#include "flutter/fml/trace_event.h" #include "third_party/tonic/converter/dart_converter.h" #include "third_party/tonic/dart_args.h" #include "third_party/tonic/dart_library_natives.h" @@ -118,6 +118,9 @@ void PlatformConfiguration::UpdateLifecycleState(const std::string& data) { void PlatformConfiguration::UpdateSemanticsEnabled(bool enabled) { std::shared_ptr dart_state = update_semantics_enabled_.dart_state().lock(); + FML_DLOG(INFO) + << "PlatformConfiguration::UpdateSemanticsEnabled is called, enabled:" + << enabled; if (!dart_state) { return; } @@ -131,6 +134,9 @@ void PlatformConfiguration::UpdateSemanticsEnabled(bool enabled) { void PlatformConfiguration::UpdateAccessibilityFeatures(int32_t values) { std::shared_ptr dart_state = update_accessibility_features_.dart_state().lock(); + FML_DLOG(INFO) + << "PlatformConfiguration::UpdateAccessibilityFeatures is called, values:" + << values; if (!dart_state) { return; } @@ -145,9 +151,7 @@ void PlatformConfiguration::DispatchPlatformMessage( std::shared_ptr dart_state = dispatch_platform_message_.dart_state().lock(); - FML_DLOG(INFO) - << "DispatchPlatformMessage channel: " - << message->channel(); + FML_DLOG(INFO) << "DispatchPlatformMessage channel: " << message->channel(); if (!dart_state) { FML_DLOG(WARNING) << "Dropping platform message for lack of DartState on channel: " @@ -181,9 +185,7 @@ void PlatformConfiguration::DispatchSemanticsAction(int32_t id, fml::MallocMapping args) { std::shared_ptr dart_state = dispatch_semantics_action_.dart_state().lock(); - FML_DLOG(INFO) - << "DispatchSemanticsAction : " - << id ; + FML_DLOG(INFO) << "PlatformConfiguration::DispatchSemanticsAction : " << id; if (!dart_state) { return; } @@ -361,7 +363,8 @@ Dart_Handle PlatformConfigurationNativeApi::SendPortPlatformMessage( void PlatformConfigurationNativeApi::RespondToPlatformMessage( int response_id, const tonic::DartByteData& data) { - FML_DLOG(INFO)<<"PlatformConfigurationNativeApi::RespondToPlatformMessage:" << response_id; + FML_DLOG(INFO) << "PlatformConfigurationNativeApi::RespondToPlatformMessage:" + << response_id; if (Dart_IsNull(data.dart_handle())) { UIDartState::Current() ->platform_configuration() diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index 07db7f9d71..dfb6cdeec2 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -175,6 +175,7 @@ bool RuntimeController::SetSemanticsEnabled(bool enabled) { if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) { platform_configuration->UpdateSemanticsEnabled( platform_data_.semantics_enabled); + FML_DLOG(INFO)<<"RuntimeController::SetSemanticsEnabled, enable="<UpdateAccessibilityFeatures( platform_data_.accessibility_feature_flags_); + FML_DLOG(INFO)<<"RuntimeController::SetAccessibilityFeatures="; return true; } @@ -286,6 +288,7 @@ bool RuntimeController::DispatchSemanticsAction(int32_t id, if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) { platform_configuration->DispatchSemanticsAction(id, action, std::move(args)); + FML_DLOG(INFO) << "RuntimeController::DispatchSemanticsAction, id="< accessibilityFocusedSemanticsNode; - if (accessibilityFocusedSemanticsNode != nullptr - && accessibilityFocusedSemanticsNode->id == node.id - && !isHadFlag - && node.HasFlag(FLAGS_::kIsSelected)) { + // todo:当前焦点语义节点 + bool isHadFlag = false; // 这里判断previousFlag和当前flag是否相同 + std::shared_ptr accessibilityFocusedSemanticsNode; + if (accessibilityFocusedSemanticsNode != nullptr && + accessibilityFocusedSemanticsNode->id == node.id && !isHadFlag && + node.HasFlag(FLAGS_::kIsSelected)) { // todo:创建并发送事件 // AccessibilityEvent event = obtainAccessibilityEvent( // node.id, AccessibilityEvent.TYPE_VIEW_SELECTED); // event.getText().add(object.label); // sendAccessibilityEvent(event); - } + } - //todo: 若该对象是输入焦点节点,且发生更新变化,则发送给os有关它的信息 - std::shared_ptr inputFocusedSemanticsNode; //当前输入焦点节点 - std::shared_ptr lastInputFocusedSemanticsNode; //上一个输入焦点节点 - if (inputFocusedSemanticsNode != nullptr - && inputFocusedSemanticsNode->id == node.id - && (lastInputFocusedSemanticsNode == nullptr - || lastInputFocusedSemanticsNode->id != inputFocusedSemanticsNode->id)) { + // todo: 若该对象是输入焦点节点,且发生更新变化,则发送给os有关它的信息 + std::shared_ptr + inputFocusedSemanticsNode; // 当前输入焦点节点 + std::shared_ptr + lastInputFocusedSemanticsNode; // 上一个输入焦点节点 + if (inputFocusedSemanticsNode != nullptr && + inputFocusedSemanticsNode->id == node.id && + (lastInputFocusedSemanticsNode == nullptr || + lastInputFocusedSemanticsNode->id != inputFocusedSemanticsNode->id)) { // 上次输入焦点节点 -> 当前输入焦点节点 lastInputFocusedSemanticsNode = inputFocusedSemanticsNode; // 发送相应的输入焦点改变事件 // sendAccessibilityEvent(obtainAccessibilityEvent(object.id, // AccessibilityEvent.TYPE_VIEW_FOCUSED)); - } else if (inputFocusedSemanticsNode == nullptr) { + } else if (inputFocusedSemanticsNode == nullptr) { // There's no TYPE_VIEW_CLEAR_FOCUSED event, so if the current input focus // becomes null, then we just set the last one to null too, so that it // sends the event again when something regains focus. lastInputFocusedSemanticsNode = nullptr; - } + } - if (inputFocusedSemanticsNode != nullptr - && inputFocusedSemanticsNode->id == node.id - && isHadFlag - && node.HasFlag(FLAGS_::kIsTextField) - // If we have a TextField that has InputFocus, we should avoid announcing it if something - // else we track has a11y focus. This needs to still work when, e.g., IME has a11y focus - // or the "PASTE" popup is used though. - // See more discussion at https://github.com/flutter/flutter/issues/23180 - && (accessibilityFocusedSemanticsNode == nullptr - || (accessibilityFocusedSemanticsNode->id == inputFocusedSemanticsNode->id))) { + if (inputFocusedSemanticsNode != nullptr && + inputFocusedSemanticsNode->id == node.id && isHadFlag && + node.HasFlag(FLAGS_::kIsTextField) + // If we have a TextField that has InputFocus, we should avoid + // announcing it if something else we track has a11y focus. This needs + // to still work when, e.g., IME has a11y focus or the "PASTE" popup is + // used though. See more discussion at + // https://github.com/flutter/flutter/issues/23180 + && (accessibilityFocusedSemanticsNode == nullptr || + (accessibilityFocusedSemanticsNode->id == + inputFocusedSemanticsNode->id))) { // 这里写输入框更新文字内容,将老旧的文本替换为新输入文字,并发送textchange事件 // AccessibilityEvent event = createTextChangedEvent(object.id, oldValue, // newValue); sendAccessibilityEvent(event); @@ -155,10 +157,35 @@ void OhosAccessibilityBridge::updateSemantics( // selectionEvent.setItemCount(newValue.length()); // sendAccessibilityEvent(selectionEvent); } - } + } } } - + // kTap = 1 << 0, + // kLongPress = 1 << 1, + // kScrollLeft = 1 << 2, + // kScrollRight = 1 << 3, + // kScrollUp = 1 << 4, + // kScrollDown = 1 << 5, + // kIncrease = 1 << 6, + // kDecrease = 1 << 7, + // kShowOnScreen = 1 << 8, + // kMoveCursorForwardByCharacter = 1 << 9, + // kMoveCursorBackwardByCharacter = 1 << 10, + // kSetSelection = 1 << 11, + // kCopy = 1 << 12, + // kCut = 1 << 13, + // kPaste = 1 << 14, + // kDidGainAccessibilityFocus = 1 << 15, + // kDidLoseAccessibilityFocus = 1 << 16, + // kCustomAction = 1 << 17, + // kDismiss = 1 << 18, + // kMoveCursorForwardByWord = 1 << 19, + // kMoveCursorBackwardByWord = 1 << 20, + // kSetText = 1 << 21, + +int32_t convertToInt32(flutter::SemanticsAction inputAction) { + return static_cast(inputAction); +} void OhosAccessibilityBridge::performAction(int32_t virtualViewId, int32_t inputAction) { // TODO 根据输入的action进行相应的响应操作 diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 57ccc87f9f..a3eeb12d45 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -28,7 +28,10 @@ // #include "flutter/shell/platform/ohos/accessibility/native_interface_accessibility.h" namespace flutter { + typedef flutter::SemanticsFlags FLAGS_; +typedef flutter::SemanticsAction ACTIONS_; + /** * flutter和ohos的无障碍服务桥接 */ @@ -52,6 +55,7 @@ class OhosAccessibilityBridge { // flutter::SemanticsFlags flags_; flutter::SemanticsNode getRootSemanticsNode(); + int32_t convertToInt32(flutter::SemanticsAction inputAction); // native os interfaces int32_t FindFocusedAccessibilityNode(int64_t elementId, @@ -62,6 +66,7 @@ class OhosAccessibilityBridge { int32_t direction, int32_t requestId, int32_t elementList); + }; class ArkUI_AccessibilityElementInfo { @@ -151,5 +156,31 @@ struct SemanticsNode { }; */ +/** + enum class SemanticsAction : int32_t { + kTap = 1 << 0, + kLongPress = 1 << 1, + kScrollLeft = 1 << 2, + kScrollRight = 1 << 3, + kScrollUp = 1 << 4, + kScrollDown = 1 << 5, + kIncrease = 1 << 6, + kDecrease = 1 << 7, + kShowOnScreen = 1 << 8, + kMoveCursorForwardByCharacter = 1 << 9, + kMoveCursorBackwardByCharacter = 1 << 10, + kSetSelection = 1 << 11, + kCopy = 1 << 12, + kCut = 1 << 13, + kPaste = 1 << 14, + kDidGainAccessibilityFocus = 1 << 15, + kDidLoseAccessibilityFocus = 1 << 16, + kCustomAction = 1 << 17, + kDismiss = 1 << 18, + kMoveCursorForwardByWord = 1 << 19, + kMoveCursorBackwardByWord = 1 << 20, + kSetText = 1 << 21, +}; + */ } // namespace flutter #endif // OHOS_ACCESSIBILITY_BRIDGE_H diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets index 7246ee6213..6f69166b87 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets @@ -36,7 +36,7 @@ export default class AccessibilityChannel implements MessageHandler{ onMessage(message: object, reply: Reply): void { if (this.handler == null) { - Log.i(AccessibilityChannel.TAG, "NULL"); + Log.i(AccessibilityChannel.TAG, "handler = NULL"); reply.reply(StringUtils.stringToArrayBuffer("")); return; } @@ -92,16 +92,19 @@ export default class AccessibilityChannel implements MessageHandler{ onOhosAccessibilityEnabled(): void { let replyId: number = this.nextReplyId++; this.flutterNapi.setSemanticsEnabled(true, replyId); + Log.i(AccessibilityChannel.TAG, "onOhosAccessibilityEnabled = true"); } onOhosAccessibilityFeatures(accessibilityFeatureFlags: number): void { let replyId: number = this.nextReplyId++; this.flutterNapi.setAccessibilityFeatures(accessibilityFeatureFlags, replyId); + Log.i(AccessibilityChannel.TAG, "onOhosAccessibilityFeatures"); } dispatchSemanticsAction(virtualViewId: number, action: Action): void { let replyId: number = this.nextReplyId++; this.flutterNapi.dispatchSemanticsAction(virtualViewId, action, replyId); + Log.i(AccessibilityChannel.TAG, "dispatchSemanticsAction"); } setAccessibilityMessageHandler(handler: AccessibilityMessageHandler): void { -- Gitee From a448b70d5eb183ab55dd9c4fead2ab81550919b2 Mon Sep 17 00:00:00 2001 From: liujiake Date: Sat, 31 Aug 2024 18:32:22 +0800 Subject: [PATCH 006/151] =?UTF-8?q?=E5=AE=9E=E7=8E=B0AccessibilityChannel.?= =?UTF-8?q?ets=E4=B8=ADhandler=E7=9A=84announce=E6=8E=A5=E5=8F=A3=EF=BC=8C?= =?UTF-8?q?=E6=8E=89=E7=94=A8=E5=88=B0ohos=5Faccessibility=5Fbridge.cpp?= =?UTF-8?q?=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- .../ohos_accessibility_bridge.cpp | 11 +++++++ .../accessibility/ohos_accessibility_bridge.h | 9 ++++-- .../src/main/cpp/types/libflutter/index.d.ets | 2 ++ .../ets/embedding/engine/FlutterEngine.ets | 27 +++++++++++++++- .../systemchannels/AccessibilityChannel.ets | 31 ++++++++++++++++++- shell/platform/ohos/library_loader.cpp | 3 ++ .../ohos/napi/platform_view_ohos_napi.cpp | 22 +++++++++++++ .../ohos/napi/platform_view_ohos_napi.h | 3 ++ 8 files changed, 104 insertions(+), 4 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 33f705c271..6f10287c1f 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -23,6 +23,17 @@ namespace flutter { OhosAccessibilityBridge::OhosAccessibilityBridge() = default; OhosAccessibilityBridge::~OhosAccessibilityBridge() = default; +OhosAccessibilityBridge& OhosAccessibilityBridge::GetInstance() +{ + static OhosAccessibilityBridge ohosAccessibilityBridge; + return ohosAccessibilityBridge; +} + +void OhosAccessibilityBridge::announce(std::unique_ptr& message) { + FML_DLOG(INFO) << ("Native C++ OhosAccessibilityBridge::announce message: ") << (message.get()); + return; +} + flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateSemanticsNode( int32_t id) { flutter::SemanticsNode node; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 57ccc87f9f..4e269933ff 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -33,9 +33,14 @@ typedef flutter::SemanticsFlags FLAGS_; * flutter和ohos的无障碍服务桥接 */ class OhosAccessibilityBridge { - public: + private: OhosAccessibilityBridge(); - ~OhosAccessibilityBridge(); + + public: + ~OhosAccessibilityBridge(); + static OhosAccessibilityBridge& GetInstance(); + + void announce(std::unique_ptr& message); void updateSemantics(flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions); diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets index 992a4e64d0..ed3f83dfaf 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets @@ -144,3 +144,5 @@ export const nativeDecodeUtf8: (array: Uint8Array) => string; export const nativeSetAccessibilityFeatures: (accessibilityFeatureFlags: number, responseId: number) => void; export const nativeAccessibilityStateChange: (state: Boolean) => string; + +export const nativeAnounce: (message: string) => string; \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterEngine.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterEngine.ets index cd3cd81923..db8dd00969 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterEngine.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterEngine.ets @@ -34,11 +34,12 @@ import SystemChannel from './systemchannels/SystemChannel'; import MouseCursorChannel from './systemchannels/MouseCursorChannel'; import RestorationChannel from './systemchannels/RestorationChannel'; import LocalizationChannel from './systemchannels/LocalizationChannel'; -import AccessibilityChannel from './systemchannels/AccessibilityChannel'; +import AccessibilityChannel, { AccessibilityMessageHandler } from './systemchannels/AccessibilityChannel'; import LocalizationPlugin from '../../plugin/localization/LocalizationPlugin' import SettingsChannel from './systemchannels/SettingsChannel'; import PlatformViewsController from '../../plugin/platform/PlatformViewsController'; import { FlutterRenderer } from './renderer/FlutterRenderer'; +import { ByteBuffer } from '../../util/ByteBuffer'; const TAG = "FlutterEngine"; @@ -123,6 +124,7 @@ export default class FlutterEngine implements EngineLifecycleListener{ this.localeChannel = new LocalizationChannel(this.dartExecutor); this.accessibilityChannel = new AccessibilityChannel(this.dartExecutor, this.flutterNapi); + this.accessibilityChannel.setAccessibilityMessageHandler(new AccessibilityMessageHandlerImp()); this.flutterNapi.addEngineLifecycleListener(this); this.localizationPlugin = new LocalizationPlugin(context, this.localeChannel); @@ -288,4 +290,27 @@ export interface EngineLifecycleListener { onPreEngineRestart(): void; onEngineWillDestroy(): void; +} +export class AccessibilityMessageHandlerImp implements AccessibilityMessageHandler { + announce(message: string): void { + Log.d(TAG, "handler announce."); + } + onTap(nodeId: number): void { + Log.d(TAG, "handler onTap."); + } + onLongPress(nodeId: number): void { + Log.d(TAG, "handler onLongPress."); + } + onTooltip(nodeId: string): void { + Log.d(TAG, "handler onTooltip."); + } + updateSemantics(buffer: ByteBuffer, strings: string[], stringAttributeArgs: ByteBuffer[]): void { + Log.d(TAG, "handler updateSemantics"); + } + updateCustomAccessibilityActions(buffer: ByteBuffer, strings: string[]): void { + Log.d(TAG, "handler updateCustomAccessibilityActions"); + } + accessibilityStateChange(state: Boolean): void{ + Log.d(TAG, "handler accessibilityStateChange"); + } } \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets index 7246ee6213..8acf0e7a66 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets @@ -22,6 +22,8 @@ import { Action } from '../../../view/AccessibilityBridge' import StandardMessageCodec from '../../../plugin/common/StandardMessageCodec'; import StringUtils from '../../../util/StringUtils'; import Any from '../../../plugin/common/Any'; +import flutter from 'libflutter.so'; +import { ByteBuffer } from '../../../util/ByteBuffer'; /** * 辅助功能channel @@ -31,7 +33,7 @@ export default class AccessibilityChannel implements MessageHandler{ private static CHANNEL_NAME = "flutter/accessibility"; private channel: BasicMessageChannel; private flutterNapi: FlutterNapi; - private handler: AccessibilityMessageHandler | null = null; + private handler: AccessibilityMessageHandler = new DefaultHandler(); private nextReplyId: number = 1; onMessage(message: object, reply: Reply): void { @@ -50,6 +52,7 @@ export default class AccessibilityChannel implements MessageHandler{ Log.i(AccessibilityChannel.TAG, "Announce"); let announceMessage: string = data.get("message"); if (announceMessage != null) { + Log.i(AccessibilityChannel.TAG, "message is " + announceMessage); this.handler.announce(announceMessage); } break; @@ -117,4 +120,30 @@ export interface AccessibilityMessageHandler extends AccessibilityDelegate { onTap(nodeId: number): void; onLongPress(nodeId: number): void; onTooltip(nodeId: string): void; +} + +export class DefaultHandler implements AccessibilityMessageHandler { + private static TAG = "AccessibilityMessageHandler"; + announce(message: string): void { + Log.i(DefaultHandler.TAG, "handler announce."); + flutter.nativeAnnounce(message); + } + onTap(nodeId: number): void { + Log.i(DefaultHandler.TAG, "handler onTap."); + } + onLongPress(nodeId: number): void { + Log.i(DefaultHandler.TAG, "handler onLongPress."); + } + onTooltip(nodeId: string): void { + Log.i(DefaultHandler.TAG, "handler onTooltip."); + } + updateSemantics(buffer: ByteBuffer, strings: string[], stringAttributeArgs: ByteBuffer[]): void { + Log.i(DefaultHandler.TAG, "handler updateSemantics"); + } + updateCustomAccessibilityActions(buffer: ByteBuffer, strings: string[]): void { + Log.i(DefaultHandler.TAG, "handler updateCustomAccessibilityActions"); + } + accessibilityStateChange(state: Boolean): void{ + Log.i(DefaultHandler.TAG, "handler accessibilityStateChange"); + } } \ No newline at end of file diff --git a/shell/platform/ohos/library_loader.cpp b/shell/platform/ohos/library_loader.cpp index 1c71193f23..e70264a03f 100644 --- a/shell/platform/ohos/library_loader.cpp +++ b/shell/platform/ohos/library_loader.cpp @@ -142,6 +142,9 @@ static napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_FUNCTION( "nativeAccessibilityStateChange", flutter::PlatformViewOHOSNapi::nativeAccessibilityStateChange), + DECLARE_NAPI_FUNCTION( + "nativeAnnounce", + flutter::PlatformViewOHOSNapi::nativeAnnounce), }; diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index 28ba0ade26..8b08c18031 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -32,6 +32,7 @@ #include "flutter/shell/platform/ohos/surface/ohos_native_window.h" #include "flutter/shell/platform/ohos/types.h" #include "unicode/uchar.h" +#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" #define OHOS_SHELL_HOLDER (reinterpret_cast(shell_holder)) namespace flutter { @@ -1832,4 +1833,25 @@ napi_value PlatformViewOHOSNapi::nativeAccessibilityStateChange( return nullptr; } +napi_value PlatformViewOHOSNapi::nativeAnnounce( + napi_env env, + napi_callback_info info) { + + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + size_t length = 0; + napi_get_value_string_utf8(env, args[0], nullptr, 0, &length); + + auto null_terminated_length = length + 1; + auto char_array = std::make_unique(null_terminated_length); + napi_get_value_string_utf8(env, args[0], char_array.get(), + null_terminated_length, nullptr); + LOGD("1535 PlatformViewOHOSNapi::nativeAnnounce message: %{public}s", char_array.get()); + OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge.announce(char_array); + return nullptr; +} + } // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h index 45dcb187d2..f44e25dc33 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.h +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -205,6 +205,9 @@ class PlatformViewOHOSNapi { static napi_value nativeAccessibilityStateChange( napi_env env, napi_callback_info info); + static napi_value nativeAnnounce( + napi_env env, + napi_callback_info info); private: static napi_env env_; -- Gitee From a6f2778b47f4f4733c921b2253334574eaf64e69 Mon Sep 17 00:00:00 2001 From: zjxi Date: Sat, 31 Aug 2024 20:19:48 +0800 Subject: [PATCH 007/151] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9Eupdatesemantics?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E8=B0=83=E7=94=A8=E5=88=86=E6=9E=90debug?= =?UTF-8?q?=E6=97=A5=E5=BF=97=EF=BC=8C=E4=BB=A5=E5=8F=8A=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E6=97=A0=E9=9A=9C=E7=A2=8D=E6=9C=8D=E5=8A=A1=E5=BC=80=E5=90=AF?= =?UTF-8?q?=E7=9B=91=E5=90=AC=E7=BB=93=E6=9E=9C=E8=B0=83=E7=94=A8=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- runtime/runtime_controller.cc | 3 +- shell/common/engine.cc | 4 ++ shell/common/shell.cc | 5 +- shell/platform/ohos/BUILD.gn | 2 + .../ohos_accessibility_bridge.cpp | 60 ++++++++++--------- .../accessibility/ohos_accessibility_bridge.h | 15 ++--- .../ohos_accessibility_manager.cpp | 35 +++++++++++ .../ohos_accessibility_manager.h | 39 ++++++++++++ .../flutter/src/main/ets/view/FlutterView.ets | 4 +- .../ohos/napi/platform_view_ohos_napi.cpp | 36 ++++++++--- .../ohos/napi/platform_view_ohos_napi.h | 3 + shell/platform/ohos/platform_view_ohos.cpp | 3 +- 12 files changed, 161 insertions(+), 48 deletions(-) create mode 100644 shell/platform/ohos/accessibility/ohos_accessibility_manager.cpp create mode 100644 shell/platform/ohos/accessibility/ohos_accessibility_manager.h diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index dfb6cdeec2..540ad7452b 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -320,8 +320,9 @@ void RuntimeController::Render(Scene* scene) { void RuntimeController::UpdateSemantics(SemanticsUpdate* update) { if (platform_data_.semantics_enabled) { client_.UpdateSemantics(update->takeNodes(), update->takeActions()); - FML_DLOG(INFO) << "RuntimeController::UpdateSemantics"; + FML_DLOG(INFO) << "RuntimeController::UpdateSemantics is called"; } + FML_DLOG(INFO) << "RuntimeController::UpdateSemantics, platform_data_.semantics_enabled = false"; } // |PlatformConfigurationClient| diff --git a/shell/common/engine.cc b/shell/common/engine.cc index bbdf61cac7..a585203938 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -419,14 +419,17 @@ void Engine::DispatchPointerDataPacket( void Engine::DispatchSemanticsAction(int id, SemanticsAction action, fml::MallocMapping args) { + FML_DLOG(INFO)<<"Engine::DispatchSemanticsAction, id="<DispatchSemanticsAction(id, action, std::move(args)); } void Engine::SetSemanticsEnabled(bool enabled) { + FML_DLOG(INFO)<<"Engine::SetSemanticsEnabled, enabled="<SetSemanticsEnabled(enabled); } void Engine::SetAccessibilityFeatures(int32_t flags) { + FML_DLOG(INFO)<<"Engine::SetAccessibilityFeatures, flags="<SetAccessibilityFeatures(flags); } @@ -466,6 +469,7 @@ void Engine::Render(std::shared_ptr layer_tree) { void Engine::UpdateSemantics(SemanticsNodeUpdates update, CustomAccessibilityActionUpdates actions) { + FML_DLOG(INFO)<<"Engine::UpdateSemantics is called"; delegate_.OnEngineUpdateSemantics(std::move(update), std::move(actions)); } diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 72358c8f59..c2a626b0c3 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1005,6 +1005,7 @@ void Shell::OnPlatformViewDispatchSemanticsAction(int32_t id, fml::MakeCopyable([engine = engine_->GetWeakPtr(), id, action, args = std::move(args)]() mutable { if (engine) { + FML_DLOG(INFO) << "Shell::OnPlatformViewDispatchSemanticsAction, id="<DispatchSemanticsAction(id, action, std::move(args)); } })); @@ -1018,6 +1019,7 @@ void Shell::OnPlatformViewSetSemanticsEnabled(bool enabled) { task_runners_.GetUITaskRunner()->PostTask( [engine = engine_->GetWeakPtr(), enabled] { if (engine) { + FML_DLOG(INFO) << "Shell::OnPlatformViewSetSemanticsEnabled, enabled="<SetSemanticsEnabled(enabled); } }); @@ -1031,6 +1033,7 @@ void Shell::OnPlatformViewSetAccessibilityFeatures(int32_t flags) { task_runners_.GetUITaskRunner()->PostTask( [engine = engine_->GetWeakPtr(), flags] { if (engine) { + FML_DLOG(INFO) << "Shell::OnPlatformViewSetAccessibilityFeatures, flags="<SetAccessibilityFeatures(flags); } }); @@ -1214,8 +1217,8 @@ void Shell::OnEngineUpdateSemantics(SemanticsNodeUpdates update, [view = platform_view_->GetWeakPtr(), update = std::move(update), actions = std::move(actions)] { if (view) { - view->UpdateSemantics(update, actions); FML_DLOG(INFO) << "Shell::OnEngineUpdateSemantics is called"; + view->UpdateSemantics(update, actions); } }); } diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn index 1af34507dd..f10efdbb73 100644 --- a/shell/platform/ohos/BUILD.gn +++ b/shell/platform/ohos/BUILD.gn @@ -86,6 +86,7 @@ source_set("flutter_ohos_sources") { "ohos_logging.h", "platform_view_ohos_delegate.h", "./accessibility/ohos_accessibility_bridge.h", + "./accessibility/ohos_accessibility_manager.h", ] #configs += [ "//flutter/shell/platform/ohos/config:gtk" ] @@ -118,6 +119,7 @@ source_set("flutter_ohos_sources") { "./surface/ohos_snapshot_surface_producer.cpp", "platform_view_ohos_delegate.cpp", "./accessibility/ohos_accessibility_bridge.cpp", + "./accessibility/ohos_accessibility_manager.cpp", ] # Set flag to stop headers being directly included (library users should not do this) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 1aff0d9d58..cec4e3ee6a 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -15,13 +15,18 @@ #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" #include "flutter/fml/logging.h" -// #include -// "flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h" namespace flutter { -OhosAccessibilityBridge::OhosAccessibilityBridge() = default; -OhosAccessibilityBridge::~OhosAccessibilityBridge() = default; +OhosAccessibilityBridge::OhosAccessibilityBridge() { + // 判断是否开启无障碍服务 + bool isAccessibilityEnabled = this->ax_manager_->getOhosAccessibilityEnabled(); + if (isAccessibilityEnabled) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::OhosAccessibilityBridge " + "isOhosAccessibilityEnabled = true"; + } +} +OhosAccessibilityBridge::~OhosAccessibilityBridge() {}; OhosAccessibilityBridge& OhosAccessibilityBridge::GetInstance() { @@ -48,7 +53,8 @@ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateSemanticsNode( void OhosAccessibilityBridge::updateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { - FML_DLOG(INFO) << ("Native C++ OhosAccessibilityBridge::updateSemantics is called"); + FML_DLOG(INFO) + << ("Native C++ OhosAccessibilityBridge::updateSemantics is called"); // 遍历更新的actions,并将所有的actions的id添加进actionMap for (const auto& item : actions) { @@ -171,28 +177,28 @@ void OhosAccessibilityBridge::updateSemantics( } } } - // kTap = 1 << 0, - // kLongPress = 1 << 1, - // kScrollLeft = 1 << 2, - // kScrollRight = 1 << 3, - // kScrollUp = 1 << 4, - // kScrollDown = 1 << 5, - // kIncrease = 1 << 6, - // kDecrease = 1 << 7, - // kShowOnScreen = 1 << 8, - // kMoveCursorForwardByCharacter = 1 << 9, - // kMoveCursorBackwardByCharacter = 1 << 10, - // kSetSelection = 1 << 11, - // kCopy = 1 << 12, - // kCut = 1 << 13, - // kPaste = 1 << 14, - // kDidGainAccessibilityFocus = 1 << 15, - // kDidLoseAccessibilityFocus = 1 << 16, - // kCustomAction = 1 << 17, - // kDismiss = 1 << 18, - // kMoveCursorForwardByWord = 1 << 19, - // kMoveCursorBackwardByWord = 1 << 20, - // kSetText = 1 << 21, +// kTap = 1 << 0, +// kLongPress = 1 << 1, +// kScrollLeft = 1 << 2, +// kScrollRight = 1 << 3, +// kScrollUp = 1 << 4, +// kScrollDown = 1 << 5, +// kIncrease = 1 << 6, +// kDecrease = 1 << 7, +// kShowOnScreen = 1 << 8, +// kMoveCursorForwardByCharacter = 1 << 9, +// kMoveCursorBackwardByCharacter = 1 << 10, +// kSetSelection = 1 << 11, +// kCopy = 1 << 12, +// kCut = 1 << 13, +// kPaste = 1 << 14, +// kDidGainAccessibilityFocus = 1 << 15, +// kDidLoseAccessibilityFocus = 1 << 16, +// kCustomAction = 1 << 17, +// kDismiss = 1 << 18, +// kMoveCursorForwardByWord = 1 << 19, +// kMoveCursorBackwardByWord = 1 << 20, +// kSetText = 1 << 21, int32_t convertToInt32(flutter::SemanticsAction inputAction) { return static_cast(inputAction); diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 6260033949..518544e1fd 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -21,11 +21,10 @@ #include #include "flutter/fml/log_level.h" -// #include "flutter/fml/macros.h" -#include "flutter/lib/ui/semantics/semantics_node.h" -// #include "flutter/shell/platform/common/accessibility_bridge.h" #include "flutter/lib/ui/semantics/custom_accessibility_action.h" -// #include "flutter/shell/platform/ohos/accessibility/native_interface_accessibility.h" +#include "flutter/lib/ui/semantics/semantics_node.h" +#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_manager.h" +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" namespace flutter { @@ -47,21 +46,24 @@ class OhosAccessibilityBridge { void updateSemantics(flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions); + // obtain the flutter semnatics node flutter::SemanticsNode getOrCreateSemanticsNode(int32_t id); void performAction(int32_t virtualViewId, int32_t inputAction); private: + std::shared_ptr ax_manager_; std::unordered_map flutterSemanticsTree_; std::unordered_map actions_mp_; - flutter::SemanticsNode semanticsNode_; - // flutter::SemanticsFlags flags_; + + flutter::SemanticsNode getRootSemanticsNode(); int32_t convertToInt32(flutter::SemanticsAction inputAction); + // native os interfaces int32_t FindFocusedAccessibilityNode(int64_t elementId, int32_t focusType, @@ -71,7 +73,6 @@ class OhosAccessibilityBridge { int32_t direction, int32_t requestId, int32_t elementList); - }; class ArkUI_AccessibilityElementInfo { diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_manager.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_manager.cpp new file mode 100644 index 0000000000..9e63609765 --- /dev/null +++ b/shell/platform/ohos/accessibility/ohos_accessibility_manager.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development 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 "flutter/shell/platform/ohos/accessibility/ohos_accessibility_manager.h" +#include "flutter/fml/logging.h" + +namespace flutter { +OhosAccessibilityManager::OhosAccessibilityManager() {}; +OhosAccessibilityManager::~OhosAccessibilityManager() {}; + +void OhosAccessibilityManager::onAccessibilityStateChanged( + bool isOhosAccessibilityEnabled) {}; + +void OhosAccessibilityManager::setOhosAccessibilityEnabled(bool isEnabled) { + FML_DLOG(INFO) << "OhosAccessibilityManager::setOhosAccessibilityEnabled = " + << isEnabled; + this->isOhosAccessibilityEnabled_ = isEnabled; +} + +bool OhosAccessibilityManager::getOhosAccessibilityEnabled() { + return this->isOhosAccessibilityEnabled_; +} + +} // namespace flutter diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_manager.h b/shell/platform/ohos/accessibility/ohos_accessibility_manager.h new file mode 100644 index 0000000000..1e8dd7f0cd --- /dev/null +++ b/shell/platform/ohos/accessibility/ohos_accessibility_manager.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development 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 OHOS_ACCESSIBILITY_MANAGER_H +#define OHOS_ACCESSIBILITY_MANAGER_H + +// #include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" + +namespace flutter { +/** + * 无障碍辅助管理类 + */ +class OhosAccessibilityManager { + public: + OhosAccessibilityManager(); + ~OhosAccessibilityManager(); + + void onAccessibilityStateChanged(bool isOhosAccessibilityEnabled); + bool getOhosAccessibilityEnabled(); + void setOhosAccessibilityEnabled(bool isEnabled); + + private: + bool isOhosAccessibilityEnabled_; +}; + +} // namespace flutter + +#endif \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index e646144729..75e449666f 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -107,6 +107,7 @@ export class FlutterView { this.mainWindow?.on('windowSizeChange', this.windowSizeChangeCallback); this.mainWindow?.on('avoidAreaChange', this.avoidAreaChangeCallback); this.mainWindow?.on('windowStatusChange', this.windowStatusChangeCallback); + accessibility.on('accessibilityStateChange', (data: boolean) => { Log.i(TAG, `subscribe accessibility state change, result: ${JSON.stringify(data)}`); this.flutterEngine?.getFlutterNapi()?.accessibilityStateChange(data); @@ -278,8 +279,7 @@ export class FlutterView { if (this.checkFullScreen && FlutterManager.getInstance().getFullScreenListener().useFullScreen()) { // 全屏显示 this.viewportMetrics.physicalViewPaddingTop = systemAvoidArea?.topRect.height ?? 0; this.viewportMetrics.physicalViewPaddingBottom = navigationAvoidArea?.bottomRect.height ?? 0; - } else { // 非全屏显示(保持规避效果) - // 顶部状态栏和底部导航栏规避为0,无平滑过渡效果 + } else { this.viewportMetrics.physicalViewPaddingTop = 0; this.viewportMetrics.physicalViewPaddingBottom = 0; } diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index 8b08c18031..3a442bc21e 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1808,7 +1808,7 @@ napi_value PlatformViewOHOSNapi::nativeUpdateSemantics( napi_env env, napi_callback_info info) { // TODO ets calls c++ - + return nullptr; } @@ -1819,17 +1819,37 @@ napi_value PlatformViewOHOSNapi::nativeUpdateCustomAccessibilityActions( return nullptr; } - +/** + * 监听获取系统的无障碍服务是否开启 + */ napi_value PlatformViewOHOSNapi::nativeAccessibilityStateChange( - napi_env env, - napi_callback_info info) { + napi_env env, + napi_callback_info info) { + napi_status ret; size_t argc = 1; napi_value args[1] = {nullptr}; - LOGD("PlatformViewOHOSNapi::nativeAccessibilityStateChange"); - napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeAccessibilityStateChange " + "napi_get_cb_info error:" + << ret; + return nullptr; + } bool state = false; - napi_get_value_bool(env, args[0], &state); - LOGD("PlatformViewOHOSNapi::nativeAccessibilityStateChange state is: %{public}s", (state ? "ture" : "false")); + ret = napi_get_value_bool(env, args[0], &state); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeAccessibilityStateChange " + "napi_get_value_bool error:" + << ret; + return nullptr; + } + LOGD( + "PlatformViewOHOSNapi::nativeAccessibilityStateChange state is: " + "%{public}s", + (state ? "true" : "false")); + // 传递到无障碍管理类 + auto ohosAccessibilityManager_ = std::make_shared(); + ohosAccessibilityManager_->setOhosAccessibilityEnabled(state); return nullptr; } diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h index f44e25dc33..c5712fd93d 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.h +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -28,6 +28,8 @@ #include "flutter/shell/common/run_configuration.h" #include "flutter/shell/platform/ohos/napi_common.h" #include "napi/native_api.h" +#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_manager.h" + // class for all c++ to call js function namespace flutter { @@ -214,6 +216,7 @@ class PlatformViewOHOSNapi { napi_ref ref_napi_obj_; static std::vector system_languages; fml::RefPtr platform_task_runner_; + std::shared_ptr ohosAccessibilityManager_; }; } // namespace flutter diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index 0509472ed8..1af47e8786 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -292,14 +292,13 @@ void PlatformViewOHOS::UpdateAssetResolverByType( delegate_.UpdateAssetResolverByType(std::move(updated_asset_resolver), type); } -// todo +// todo accessbility_bridges void PlatformViewOHOS::UpdateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { FML_DLOG(INFO) << "PlatformViewOHOS::UpdateSemantics"; // platform_view_ohos_delegate_->UpdateSemantics(update, actions); ax_bridge_delegate_->updateSemantics(update, actions); - } // |PlatformView| -- Gitee From fd41fef70afa1ce481eb9cc1e454987ce1fe5485 Mon Sep 17 00:00:00 2001 From: zjxi Date: Sat, 31 Aug 2024 20:27:07 +0800 Subject: [PATCH 008/151] =?UTF-8?q?=E8=AE=BE=E7=BD=AEplatform=5Fdata.h?= =?UTF-8?q?=E4=B8=ADsemantics=5Fenabled=3Dtrue=E7=94=A8=E4=BA=8Edebug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- runtime/platform_data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/platform_data.h b/runtime/platform_data.h index ca7b683a1e..92dfdf5da7 100644 --- a/runtime/platform_data.h +++ b/runtime/platform_data.h @@ -38,7 +38,7 @@ struct PlatformData { std::vector locale_data; std::string user_settings_data = "{}"; std::string lifecycle_state; - bool semantics_enabled = false; + bool semantics_enabled = true; //debug bool assistive_technology_enabled = false; int32_t accessibility_feature_flags_ = 0; }; -- Gitee From df888edccbdb40807d71675e21a897665f629edc Mon Sep 17 00:00:00 2001 From: zjxi Date: Sat, 31 Aug 2024 20:35:44 +0800 Subject: [PATCH 009/151] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9nativeAnnounce?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=8B=BC=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../flutter/src/main/cpp/types/libflutter/index.d.ets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets index ed3f83dfaf..458a7f175d 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets @@ -145,4 +145,4 @@ export const nativeSetAccessibilityFeatures: (accessibilityFeatureFlags: number, export const nativeAccessibilityStateChange: (state: Boolean) => string; -export const nativeAnounce: (message: string) => string; \ No newline at end of file +export const nativeAnnounce: (message: string) => string; \ No newline at end of file -- Gitee From 5e40cbd71b0fba125d2c31ccc5b41e3cb4b96086 Mon Sep 17 00:00:00 2001 From: zjxi Date: Sat, 31 Aug 2024 21:15:39 +0800 Subject: [PATCH 010/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E6=97=A0?= =?UTF-8?q?=E9=9A=9C=E7=A2=8D=E6=A1=A5=E6=8E=A5=E7=B1=BB=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../accessibility/ohos_accessibility_bridge.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index cec4e3ee6a..2b74988338 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -20,7 +20,8 @@ namespace flutter { OhosAccessibilityBridge::OhosAccessibilityBridge() { // 判断是否开启无障碍服务 - bool isAccessibilityEnabled = this->ax_manager_->getOhosAccessibilityEnabled(); + bool isAccessibilityEnabled = + this->ax_manager_->getOhosAccessibilityEnabled(); if (isAccessibilityEnabled) { FML_DLOG(INFO) << "OhosAccessibilityBridge::OhosAccessibilityBridge " "isOhosAccessibilityEnabled = true"; @@ -28,14 +29,14 @@ OhosAccessibilityBridge::OhosAccessibilityBridge() { } OhosAccessibilityBridge::~OhosAccessibilityBridge() {}; -OhosAccessibilityBridge& OhosAccessibilityBridge::GetInstance() -{ - static OhosAccessibilityBridge ohosAccessibilityBridge; - return ohosAccessibilityBridge; +OhosAccessibilityBridge& OhosAccessibilityBridge::GetInstance() { + static OhosAccessibilityBridge ohosAccessibilityBridge; + return ohosAccessibilityBridge; } void OhosAccessibilityBridge::announce(std::unique_ptr& message) { - FML_DLOG(INFO) << ("Native C++ OhosAccessibilityBridge::announce message: ") << (message.get()); + FML_DLOG(INFO) << ("Native C++ OhosAccessibilityBridge::announce message: ") + << (message.get()); return; } -- Gitee From 8cb77215aa5b0ef74f346589e4a4c1db054a4e2c Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 4 Sep 2024 10:57:06 +0800 Subject: [PATCH 011/151] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8D=E6=A1=A5=E6=8E=A5=E7=B1=BB=E4=B8=AD=E9=83=A8=E5=88=86?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E5=8A=9F=E8=83=BD=E5=92=8C=E7=AE=97=E6=B3=95?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 123 ++++++++++++++++++ .../accessibility/ohos_accessibility_bridge.h | 32 ++++- 2 files changed, 150 insertions(+), 5 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 2b74988338..21a9485aa6 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -15,6 +15,7 @@ #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" #include "flutter/fml/logging.h" +#include "ohos_accessibility_bridge.h" namespace flutter { @@ -51,20 +52,71 @@ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateSemanticsNode( return node; } +/** + * 从dart侧传递到c++侧的flutter语义树节点更新过程 + */ void OhosAccessibilityBridge::updateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { FML_DLOG(INFO) << ("Native C++ OhosAccessibilityBridge::updateSemantics is called"); + std::set visitedObjs; + // SEMANTICS_NODE_ rootObj = getRootSemanticsNode(); + std::vector newRoutes; + // 遍历更新的actions,并将所有的actions的id添加进actionMap for (const auto& item : actions) { const flutter::CustomAccessibilityAction action = item.second; actions_mp_[action.id] = action; } + // Dispatch a TYPE_WINDOW_STATE_CHANGED event if the most recent route id + // changed from the + // previously cached route id. + // Finds the last route that is not in the previous routes. + // SEMANTICS_NODE_ lastAdded; + // lastAdded.id = -2; + // for (const auto& _node : newRoutes) { + // if (!flutterNavigationStack[_node.id]) { + // lastAdded = _node; + // } + // } + // // If all the routes are in the previous route, get the last route. + // if (lastAdded.id == -2 && newRoutes.size() > 0) { + // lastAdded = newRoutes[newRoutes.size() - 1]; + // } + + // There are two cases if lastAdded != nil + // 1. lastAdded is not in previous routes. In this case, + // lastAdded.id != previousRouteId + // 2. All new routes are in previous routes and + // lastAdded = newRoutes.last. + // In the first case, we need to announce new route. In the second case, + // we need to announce if one list is shorter than the other. + // if (lastAdded.id != -2 && (lastAdded.id != previousRouteId || + // newRoutes.size() != + // flutterNavigationStack.size())) { + // previousRouteId = lastAdded.id; + // onWindowNameChange(lastAdded); // todo + // } + // flutterNavigationStack.clear(); + // for (const auto& _node : newRoutes) { + // flutterNavigationStack.emplace_back(_node.id); + // } + + // for (const auto& item : flutterSemanticsTree_) { + // SEMANTICS_NODE_ obj = item.second; + // if (visitedObjs.find(obj) == visitedObjs.end()) { + // removeSemanticsNode(obj); + // flutterSemanticsTree_.erase(item.first); + // } + // } + for (auto& item : update) { const flutter::SemanticsNode& node = item.second; + printTest(node); // print node struct for debugging + // todo:根据nodeId获取当前os对应的真实节点 // currentNode = // ArkUI_AccessibilityElementInfo::createAccessibilityElementInfo(node.id); @@ -220,9 +272,15 @@ void OhosAccessibilityBridge::performAction(int32_t virtualViewId, } } +// 获取根节点 flutter::SemanticsNode OhosAccessibilityBridge::getRootSemanticsNode() { + if (flutterSemanticsTree_.size() == 0) { + FML_DLOG(ERROR) << "flutterSemanticsTree_.size() = 0"; + return flutter::SemanticsNode{}; + } return flutterSemanticsTree_.at(0); } + // 找到当前焦点触发节点 int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( int64_t elementId, @@ -240,6 +298,71 @@ int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( return 0; } +void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { + +} + +void OhosAccessibilityBridge::removeSemanticsNode( + flutter::SemanticsNode nodeToBeRemoved) { + if (flutterSemanticsTree_.find(nodeToBeRemoved.id) == + flutterSemanticsTree_.end()) { + FML_DLOG(INFO) << "Attempted to remove a node that is not in the tree."; + } + // if (flutterSemanticsTree_.at(nodeToBeRemoved.id) != nodeToBeRemoved) { + // FML_DLOG(ERROR) << "Flutter semantics tree failed to get expected node " + // "when searching by id."; + // } + // nodeToBeRemoved.parent = nullptr; + if (nodeToBeRemoved.platformViewId != -1) { + } +} + +void OhosAccessibilityBridge::printTest(flutter::SemanticsNode node) { + FML_DLOG(INFO) << "=============================================="; + FML_DLOG(INFO) << "node.id=" << node.id; + FML_DLOG(INFO) << "node.flags=" << node.flags; + FML_DLOG(INFO) << "node.actions=" << node.actions; + FML_DLOG(INFO) << "node.maxValueLength=" << node.maxValueLength; + FML_DLOG(INFO) << "node.currentValueLength=" << node.currentValueLength; + FML_DLOG(INFO) << "node.textSelectionBase=" << node.textSelectionBase; + FML_DLOG(INFO) << "node.textSelectionExtent=" << node.textSelectionExtent; + FML_DLOG(INFO) << "node.textSelectionBase=" << node.textSelectionBase; + FML_DLOG(INFO) << "node.platformViewId=" << node.platformViewId; + FML_DLOG(INFO) << "node.scrollChildren=" << node.scrollChildren; + FML_DLOG(INFO) << "node.scrollIndex=" << node.scrollIndex; + FML_DLOG(INFO) << "node.scrollPosition=" << node.scrollPosition; + FML_DLOG(INFO) << "node.scrollIndex=" << node.scrollIndex; + FML_DLOG(INFO) << "node.scrollPosition=" << node.scrollPosition; + FML_DLOG(INFO) << "node.scrollExtentMax=" << node.scrollExtentMax; + FML_DLOG(INFO) << "node.scrollExtentMin=" << node.scrollExtentMin; + FML_DLOG(INFO) << "node.elevation=" << node.elevation; + FML_DLOG(INFO) << "node.thickness=" << node.thickness; + FML_DLOG(INFO) << "node.label=" << node.label; + FML_DLOG(INFO) << "node.tooltip=" << node.tooltip; + FML_DLOG(INFO) << "node.hint=" << node.hint; + FML_DLOG(INFO) << "node.textDirection=" << node.textDirection; + FML_DLOG(INFO) << "node.childrenInTraversalOrder.size()=" + << node.childrenInTraversalOrder.size(); + for (uint32_t i = 0; i < node.childrenInTraversalOrder.size(); i++) { + FML_DLOG(INFO) << "node.childrenInTraversalOrder[" << i + << "]=" << node.childrenInTraversalOrder[i]; + } + + FML_DLOG(INFO) << "node.childrenInHitTestOrder.size()=" + << node.childrenInHitTestOrder.size(); + for (uint32_t i = 0; i < node.childrenInHitTestOrder.size(); i++) { + FML_DLOG(INFO) << "node.childrenInHitTestOrder[" << i + << "]=" << node.childrenInHitTestOrder[i]; + } + + FML_DLOG(INFO) << "node.customAccessibilityActions.size()=" + << node.customAccessibilityActions.size(); + for (uint32_t i = 0; i < node.customAccessibilityActions.size(); i++) { + FML_DLOG(INFO) << "node.customAccessibilityActions[" << i + << "]=" << node.customAccessibilityActions[i]; + } + FML_DLOG(INFO) << "=============================================="; +} void ArkUI_AccessibilityElementInfo::createAccessibilityElementInfo(int vid) { // TODO ohos和flutter虚拟节点交互,根据虚拟节点id创建真实elementinfo // ArkUI_AccessibilityElementInfo相当于安卓的view diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 518544e1fd..8f13d79f05 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -30,6 +30,7 @@ namespace flutter { typedef flutter::SemanticsFlags FLAGS_; typedef flutter::SemanticsAction ACTIONS_; +typedef flutter::SemanticsNode SEMANTICS_NODE_; /** * flutter和ohos的无障碍服务桥接 @@ -39,14 +40,14 @@ class OhosAccessibilityBridge { OhosAccessibilityBridge(); public: - ~OhosAccessibilityBridge(); + ~OhosAccessibilityBridge(); static OhosAccessibilityBridge& GetInstance(); void announce(std::unique_ptr& message); void updateSemantics(flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions); - + // obtain the flutter semnatics node flutter::SemanticsNode getOrCreateSemanticsNode(int32_t id); @@ -56,14 +57,17 @@ class OhosAccessibilityBridge { std::shared_ptr ax_manager_; std::unordered_map flutterSemanticsTree_; std::unordered_map actions_mp_; - flutter::SemanticsNode semanticsNode_; - + static const int32_t ROOT_NODE_ID = 0; + int32_t previousRouteId = ROOT_NODE_ID; + // A Java/Android cached representation of the Flutter app's navigation stack. + // The Flutter navigation stack is tracked so that accessibility announcements + // can be made during Flutter's navigation changes. + std::vector flutterNavigationStack; flutter::SemanticsNode getRootSemanticsNode(); int32_t convertToInt32(flutter::SemanticsAction inputAction); - // native os interfaces int32_t FindFocusedAccessibilityNode(int64_t elementId, int32_t focusType, @@ -73,6 +77,24 @@ class OhosAccessibilityBridge { int32_t direction, int32_t requestId, int32_t elementList); + + /** + * Informs the TalkBack user about window name changes. + * it creates a {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED} and sends + * the event to Android's accessibility system. In both cases, TalkBack + * announces the label of the route and re-addjusts the accessibility focus. + * + *

The given {@code route} should be a {@link SemanticsNode} that + * represents a navigation route in the Flutter app. + */ + void onWindowNameChange(flutter::SemanticsNode route); + /** + * Hook called just before a {@link SemanticsNode} is removed from the Android cache of Flutter's + * semantics tree. + */ + void removeSemanticsNode(flutter::SemanticsNode nodeToBeRemoved); + + void printTest(flutter::SemanticsNode node); }; class ArkUI_AccessibilityElementInfo { -- Gitee From 1d6db507a8ca21fe2b989ec9e4807deef720c9c9 Mon Sep 17 00:00:00 2001 From: liujiake Date: Wed, 4 Sep 2024 18:59:47 +0800 Subject: [PATCH 012/151] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8DXComponent=E5=9B=9E=E8=B0=83=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=B3=A8=E5=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- .../platform/ohos/ohos_xcomponent_adapter.cpp | 86 +++++++++++++++++++ shell/platform/ohos/ohos_xcomponent_adapter.h | 3 + 2 files changed, 89 insertions(+) diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp index d1b62dcd70..ac004f2d09 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.cpp +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -266,6 +266,88 @@ void XComponentBase::BindXComponentCallback() { mouseCallback_.DispatchHoverEvent = DispatchHoverEventCB; } + +/** Called when need to get element infos based on a specified node. */ +int32_t FindAccessibilityNodeInfosById( + int64_t elementId, + ArkUI_AccessibilitySearchMode mode, + int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList) +{ + LOGD("accessibilityProviderCallback_.FindAccessibilityNodeInfosById"); + return 0; +} + +/** Called when need to get element infos based on a specified node and text content. */ +int32_t FindAccessibilityNodeInfosByText( + int64_t elementId, + const char* text, + int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList) +{ + LOGD("accessibilityProviderCallback_.FindAccessibilityNodeInfosByText"); + return 0; +} + +/** Called when need to get the focused element info based on a specified node. */ +int32_t FindFocusedAccessibilityNode( + int64_t elementId, + ArkUI_AccessibilityFocusType focusType, + int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo) +{ + LOGD("accessibilityProviderCallback_.FindFocusedAccessibilityNode"); + return 0; +} + +/** Query the node that can be focused based on the reference node. Query the next node that can be focused based on the mode and direction. */ +int32_t FindNextFocusAccessibilityNode( + int64_t elementId, + ArkUI_AccessibilityFocusMoveDirection direction, + int32_t requestId, + ArkUI_AccessibilityElementInfo* elementList) +{ + LOGD("accessibilityProviderCallback_.FindNextFocusAccessibilityNode"); + return 0; +} + +/** Performing the Action operation on a specified node. */ +int32_t ExecuteAccessibilityAction( + int64_t elementId, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments *actionArguments, + int32_t requestId) +{ + LOGD("accessibilityProviderCallback_.ExecuteAccessibilityAction"); + return 0; +} + +/** Clears the focus status of the currently focused node */ +int32_t ClearFocusedFocusAccessibilityNode() +{ + LOGD("accessibilityProviderCallback_.ClearFocusedFocusAccessibilityNode"); + return 0; +} + +/** Queries the current cursor position of a specified node. */ +int32_t GetAccessibilityNodeCursorPosition( + int64_t elementId, + int32_t requestId, + int32_t* index) +{ + LOGD("accessibilityProviderCallback_.GetAccessibilityNodeCursorPosition"); + return 0; +} + +void XComponentBase::BindAccessibilityProviderCallback() { + accessibilityProviderCallback_.FindAccessibilityNodeInfosById = FindAccessibilityNodeInfosById; + accessibilityProviderCallback_.FindAccessibilityNodeInfosByText = FindAccessibilityNodeInfosByText; + accessibilityProviderCallback_.FindFocusedAccessibilityNode = FindFocusedAccessibilityNode; + accessibilityProviderCallback_.FindNextFocusAccessibilityNode = FindNextFocusAccessibilityNode; + accessibilityProviderCallback_.ExecuteAccessibilityAction = ExecuteAccessibilityAction; + accessibilityProviderCallback_.ClearFocusedFocusAccessibilityNode = ClearFocusedFocusAccessibilityNode; + accessibilityProviderCallback_.GetAccessibilityNodeCursorPosition = GetAccessibilityNodeCursorPosition; +} + XComponentBase::XComponentBase(std::string id){ id_ = id; isEngineAttached_ = false; @@ -307,6 +389,10 @@ void XComponentBase::SetNativeXComponent(OH_NativeXComponent* nativeXComponent){ BindXComponentCallback(); OH_NativeXComponent_RegisterCallback(nativeXComponent_, &callback_); OH_NativeXComponent_RegisterMouseEventCallback(nativeXComponent_, &mouseCallback_); + BindAccessibilityProviderCallback(); + ArkUI_AccessibilityProvider *accessibilityProvider = nullptr; + OH_NativeXComponent_GetNativeAccessibilityProvider(nativeXComponent, &accessibilityProvider); + OH_ArkUI_AccessibilityProviderRegisterCallback(accessibilityProvider, &accessibilityProviderCallback_); } } diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.h b/shell/platform/ohos/ohos_xcomponent_adapter.h index aecea89ded..821a203c9b 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.h +++ b/shell/platform/ohos/ohos_xcomponent_adapter.h @@ -16,6 +16,7 @@ #ifndef OHOS_XCOMPONENT_ADAPTER_H #define OHOS_XCOMPONENT_ADAPTER_H #include +#include #include #include "flutter/shell/platform/ohos/ohos_touch_processor.h" #include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" @@ -28,6 +29,7 @@ class XComponentBase { private: void BindXComponentCallback(); + void BindAccessibilityProviderCallback(); public: XComponentBase(std::string id); @@ -48,6 +50,7 @@ public: OH_NativeXComponent_TouchEvent touchEvent_; OH_NativeXComponent_Callback callback_; OH_NativeXComponent_MouseEvent_Callback mouseCallback_; + ArkUI_AccessibilityProviderCallbacks accessibilityProviderCallback_; std::string id_; std::string shellholderId_; bool isEngineAttached_; -- Gitee From 0b66e966802c2cbb0d4955ce79caa5848a2a697a Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 4 Sep 2024 19:27:57 +0800 Subject: [PATCH 013/151] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8D=E6=A1=A5=E6=8E=A5=E7=B1=BB=E7=9A=84=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=8E=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../native_interface_accessibility.cpp | 5 - .../native_interface_accessibility.h | 923 ------------------ .../ohos_accessibility_bridge.cpp | 75 +- .../accessibility/ohos_accessibility_bridge.h | 17 +- .../src/main/cpp/types/libflutter/index.d.ets | 2 +- .../main/ets/embedding/engine/FlutterNapi.ets | 3 +- .../ets/embedding/ohos/FlutterAbility.ets | 3 +- 7 files changed, 49 insertions(+), 979 deletions(-) delete mode 100644 shell/platform/ohos/accessibility/native_interface_accessibility.cpp delete mode 100644 shell/platform/ohos/accessibility/native_interface_accessibility.h diff --git a/shell/platform/ohos/accessibility/native_interface_accessibility.cpp b/shell/platform/ohos/accessibility/native_interface_accessibility.cpp deleted file mode 100644 index b56cac9704..0000000000 --- a/shell/platform/ohos/accessibility/native_interface_accessibility.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "flutter/shell/platform/ohos/accessibility/native_interface_accessibility.h" - -namespace flutter { - -} \ No newline at end of file diff --git a/shell/platform/ohos/accessibility/native_interface_accessibility.h b/shell/platform/ohos/accessibility/native_interface_accessibility.h deleted file mode 100644 index 3ea3ef9d26..0000000000 --- a/shell/platform/ohos/accessibility/native_interface_accessibility.h +++ /dev/null @@ -1,923 +0,0 @@ -/* - * 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. - */ - -/** - * @addtogroup ArkUI_Accessibility - * @{ - * - * @brief - * - * @since 13 - * @version 1.0 - */ - -/** - * @file native_interface_accessibility.h - * - * @brief - * - * @since 13 - * @version 1.0 - */ -#ifndef _NATIVE_INTERFACE_ACCESSIBILITY_H -#define _NATIVE_INTERFACE_ACCESSIBILITY_H - -#include - -#ifdef __cplusplus -extern "C"{ -#endif - -/** - * @brief Provides an encapsulated ArkUI_AccessibilityElementInfo instance. - * - * @since 13 - */ -typedef struct ArkUI_AccessibilityElementInfo ArkUI_AccessibilityElementInfo; - -/** - * @brief Defines the accessibility event info. - * - * @since 13 - */ -typedef struct ArkUI_AccessibilityEventInfo ArkUI_AccessibilityEventInfo; - -/** - * @brief Definesthe accessibility native provider. - * - * @since 13 - */ -typedef struct ArkUI_AccessibilityProvider ArkUI_AccessibilityProvider; - -/** - * @brief Provides an encapsulated OH_NativeAccessibilityDictionary instance, Implement the function of cpp dictionary. - * - * @since 13 - * @version 1.0 - */ -typedef struct ArkUI_AccessibilityActionArguments ArkUI_AccessibilityActionArguments; - -/** - * @brief Enumerates the API accessibility actions. - * - * @since 13 - * @version 1.0 - */ -typedef enum { - /** Invalid */ - ARKUI_NATIVE_ACCESSIBILITY_ACTION_INVALID = 0, - /** After receiving the event, the component needs to respond to the click. */ - ARKUI_NATIVE_ACCESSIBILITY_ACTION_CLICK = 0x00000010, - /** After receiving the event, the component needs to respond to the long click. */ - ARKUI_NATIVE_ACCESSIBILITY_ACTION_LONG_CLICK = 0x00000020, - /** Indicates the operation of obtaining the accessibility focus. The specific component is focused */ - ARKUI_NATIVE_ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS = 0x00000040, - /** Indicates the operation of clearing the accessibility focus. */ - ARKUI_NATIVE_ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080, - /** The scrolling component responds to forward scrolling action. */ - ARKUI_NATIVE_ACCESSIBILITY_ACTION_SCROLL_FORWARD = 0x00000100, - /** The scrolling component responds to backwrad scrolling action. */ - ARKUI_NATIVE_ACCESSIBILITY_ACTION_SCROLL_BACKWARD = 0x00000200, - /** Coping the selected content for the text component. */ - ARKUI_NATIVE_ACCESSIBILITY_ACTION_COPY = 0x00000400, - /** Paste the selected content for the text component. */ - ARKUI_NATIVE_ACCESSIBILITY_ACTION_PASTE = 0x00000800, - /** Cut the selected content for the text component. */ - ARKUI_NATIVE_ACCESSIBILITY_ACTION_CUT = 0x00001000, - /** Indicates the selection operation. The selectTextBegin, selectTextEnd, and selectTextInForWard parameters need to be set. Select a text segment in the edit box. */ - ARKUI_NATIVE_ACCESSIBILITY_ACTION_SET_SELECTION = 0x00002000, - /** Set the text Content for the text component. */ - ARKUI_NATIVE_ACCESSIBILITY_ACTION_SET_TEXT = 0x00004000, - /** Set the cursor position for the text component. */ - ARKUI_NATIVE_ACCESSIBILITY_ACTION_SET_CURSOR_POSITION = 0x00100000, -} ArkUI_Accessibility_ActionType; - -/** - * @brief Enumerates the API accessibility event types. - * - * @since 13 - * @version 1.0 - */ -typedef enum { - /** Invalid */ - ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_INVALID = 0, - /** Clicked event, which is sent after the UI component responds. */ - ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_CLICKED_EVENT = 0x00000001, - /** Long-Clicked event, which is sent after the UI component responds. */ - ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_LONG_CLICKED_EVENT = 0x00000002, - /** Selected event, which is sent after the UI component responds. */ - ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_SELECTED_EVENT = 0x00000004, - /** Text update event, needs to be send when the text is updated. */ - ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_TEXT_UPDATE_EVENT = 0x00000010, - /** Page update event, which is sent when the page jumps, switchs, changes in size, or moves. */ - ARKUI_NATIVE_ACCESSIBILITY_TYPE_PAGE_STATE_UPDATE = 0x00000020, - /** Content update event, which is sent when the page content changes. */ - ARKUI_NATIVE_ACCESSIBILITY_TYPE_PAGE_CONTENT_UPDATE = 0x00000800, - /** scrolled event, this event is send when a scrolling event occurs on a component that can be scrolled. */ - ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_SCROLLED_EVENT = 0x000001000, - /** Accessibility focus event, which is send after the UI component responds. */ - ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_ACCESSIBILITY_FOCUSED_EVENT = 0x00008000, - /** Accessibility focus clear event, which is send after the UI component responds. */ - ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED_EVENT = 0x00010000, - /** Request focus for accessibility event, proactively reqeust to focus on a specified node. */ - ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_REQUEST_FOCUS_FOR_ACCESSIBILITY = 0x02000000, - /** Page open event. the event is reported when the UI component */ - ARKUI_NATIVE_ACCESSIBILITY_TYPE_PAGE_OPEN = 0x20000000, - /** Page close event. the event is reported when the UI component */ - ARKUI_NATIVE_ACCESSIBILITY_TYPE_PAGE_CLOSE = 0x08000000, - /** Announce for accessibility event, requesting to actively play the specified content event. */ - ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_ANNOUNCE_FOR_ACCESSIBILITY = 0x10000000, -} ArkUI_AccessibilityEventType; - -/** - * @brief Defines the accessible of action - * - * @since 13 - * @version 1.0 - */ -typedef struct { - /** action type. */ - ArkUI_Accessibility_ActionType actionType; - /** the description message of action. */ - const char* description; -} ArkUI_AccessibleAction; - -/** - * @brief Defines the accessible of rect. - * - * @since 13 - * @version 1.0 - */ -typedef struct { - /** the left top x pixel corrdinates. */ - int32_t leftTopX; - /** the left top y pixel corrdinates. */ - int32_t leftTopY; - /** the right bottom x pixel corrdinates. */ - int32_t rightBottomX; - /** the right bottom y pixel corrdinates. */ - int32_t rightBottomY; -} ArkUI_AccessibleRect; - -/** - * @brief Defines the accessible of range info. - * - * @since 13 - * @version 1.0 - */ -typedef struct { - /** the min value. */ - double min; - /** the max value. */ - double max; - /** the current value. */ - double current; -} ArkUI_AccessibleRangeInfo; - -/** - * @brief Defines the accessible of grid info. - * - * @since 13 - * @version 1.0 - */ -typedef struct { - /** The number of row. */ - int32_t rowCount; - /** The number of column. */ - int32_t columnCount; - /** 0: select one line only, otherwise select multilines. */ - int32_t selectionMode; -} ArkUI_AccessibleGridInfo; - -/** - * @brief Defines the accessible of grid item info. - * - * @since 13 - * @version 1.0 - */ -typedef struct { - /** true: The item isHeading, otherwise is not */ - bool heading; - /** true: The item selected, otherwise is not */ - bool selected; - /** the index of column */ - int32_t columnIndex; - /** the index of row */ - int32_t rowIndex; - /** the column spanned */ - int32_t columnSpan; - /** the row spanned */ - int32_t rowSpan; -} ArkUI_AccessibleGridItemInfo; - -/** - * @brief Enumerates the API accessibility ErrorCode states. - * - * @since 13 - * @version 1.0 - */ -enum AcessbilityErrorCode{ - /** Successful. */ - OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS = 0, - /** Failed. */ - OH_ARKUI_ACCESSIBILITY_RESULT_FAILED = -1, - /** Invalid parameters. */ - OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER = -2, - /** Out of memory. */ - OH_ARKUI_ACCESSIBILITY_RESULT_OUT_OF_MEMORY = -3, -} ; - -/** - * @brief Enumerates the API accessibility search mode. - * - * @since 13 - * @version 1.0 - */ -typedef enum { - /** predecessors */ - NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS = 1 << 0, - /** slbings */ - NATIVE_SEARCH_MODE_PREFETCH_SIBLINGS = 1 << 1, - /** children */ - NATIVE_SEARCH_MODE_PREFETCH_CHILDREN = 1 << 2, - /** recusive children */ - NATIVE_SEARCH_MODE_PREFETCH_RECURSIVE_CHILDREN = 1 << 3, -} ArkUI_AccessibilitySearchMode; - -/** - * @brief Enumerates the API accessibility focus type. - * - * @since 13 - * @version 1.0 - */ -typedef enum { - /** Invalid */ - NATIVE_FOCUS_TYPE_INVALID = -1, - /** Input focus type */ - NATIVE_FOCUS_TYPE_INPUT = 1 << 0, - /** Accessibility focus type */ - NATIVE_FOCUS_TYPE_ACCESSIBILITY = 1 << 1, -} ArkUI_AccessibilityFocusType; - -/** - * @brief Enumerates the API accessibility focus move direction. - * - * @since 13 - * @version 1.0 - */ -typedef enum { - /** Invalid */ - NATIVE_DIRECTION_INVALID = 0, - /** up direction. */ - NATIVE_DIRECTION_UP = 0x00000001, - /** down direction. */ - NATIVE_DIRECTION_DOWN = 0x00000002, - /** left direction. */ - NATIVE_DIRECTION_LEFT = 0x00000004, - /** right direction. */ - NATIVE_DIRECTION_RIGHT = 0x00000008, - /** forward direction. */ - NATIVE_DIRECTION_FORWARD = 0x00000010, - /** backward direction. */ - NATIVE_DIRECTION_BACKWARD = 0x00000020, -} ArkUI_AccessibilityFocusMoveDirection; - -/** - * @brief Provides an encapsulated ArkUI_AccessibilityElementInfoList instance. - * - * @since 13 - * @version 1.0 - */ -typedef struct ArkUI_AccessibilityElementInfoList ArkUI_AccessibilityElementInfoList; - -/** - * @brief Registers the accessibility provider callbacks - * - * @since 13 - * @version 1.0 - */ -typedef struct ArkUI_AccessibilityProviderCallbacks { - /** Called when need to get element infos based on a specified node. */ - int32_t (*FindAccessibilityNodeInfosById)(int64_t elementId, ArkUI_AccessibilitySearchMode mode, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList); - /** Called when need to get element infos based on a specified node and text content. */ - int32_t (*FindAccessibilityNodeInfosByText)(int64_t elementId, const char* text, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList); - /** Called when need to get the focused element info based on a specified node. */ - int32_t (*FindFocusedAccessibilityNode)(int64_t elementId, ArkUI_AccessibilityFocusType focusType, int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo); - /** Query the node that can be focused based on the reference node. Query the next node that can be focused based on the mode and direction. */ - int32_t (*FindNextFocusAccessibilityNode)(int64_t elementId, ArkUI_AccessibilityFocusMoveDirection direction, int32_t requestId, ArkUI_AccessibilityElementInfo* elementList); - /** Performing the Action operation on a specified node. */ - int32_t (*ExecuteAccessibilityAction)(int64_t elementId, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments actionArguments, int32_t requestId); - /** Clears the focus status of the currently focused node */ - int32_t (*ClearFocusedFocusAccessibilityNode)(); - /** Queries the current cursor position of a specified node. */ - int32_t (*GetAccessibilityNodeCursorPosition)(int64_t elementId, int32_t requestId, int32_t* index); -} ArkUI_AccessibilityProviderCallbacks; - -/** - * @brief Registers a callback for this ArkUI_AccessibilityProvider instance. - * - * @param provider Indicates the pointer to this ArkUI_AccessibilityProvider instance. - * @param callbacks Indicates the pointer to a GetAccessibilityNodeCursorPosition callback. - * @return Returns the status code of the execution. - * @since 13 - * @version 1.0 - */ -int32_t OH_ArkUI_AccessibilityProviderRegisterCallback( - ArkUI_AccessibilityProvider* provider, ArkUI_AccessibilityProviderCallbacks* callbacks); - -/** - * @brief send accessibility event info. - * - * @param provider Indicates the pointer to this ArkUI_AccessibilityProvider instance. - * @param eventInfo Indicates the pointer to the accessibility event info. - * @param callback Indicates the pointer to a SendAccessibilityAsyncEvent callback. - * @return Returns the status code of the execution. - * @since 13 - * @version 1.0 - */ -void OH_ArkUI_SendAccessibilityAsyncEvent( - ArkUI_AccessibilityProvider* provider, ArkUI_AccessibilityEventInfo* eventInfo, void (*callback)(int32_t errorCode)); - -/** - * @brief Adds an element to the list. - * - * @param list Indicates the pointer to the accessibility element list. - * @return Returns the pointer to the accessibility elementInfo. - * @since 13 - * @version 1.0 - */ -ArkUI_AccessibilityElementInfo* OH_ArkUI_AddAndGetAccessibilityElementInfo(ArkUI_AccessibilityElementInfoList* list); - -/** -* @brief Sets the page id of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param pageId Indicates the page id. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoPageId(ArkUI_AccessibilityElementInfo* elementInfo, int32_t pageId); - -/** -* @brief Sets the page id of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param componentId Indicates the component id. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoComponentId(ArkUI_AccessibilityElementInfo* elementInfo, int32_t componentId); - -/** -* @brief Sets the parent id of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param parentId Indicates the parent id. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoParentId(ArkUI_AccessibilityElementInfo* elementInfo, int32_t parentId); - -/** -* @brief Sets the component type of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param componentType Indicates the component type. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoComponentType(ArkUI_AccessibilityElementInfo* elementInfo, const char* componentType); - -/** -* @brief Sets the component contents of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param contents Indicates the component contents. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoContents(ArkUI_AccessibilityElementInfo* elementInfo, const char* contents); - -/** -* @brief Sets the hint text of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param hintText Indicates the hint text. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoHintText(ArkUI_AccessibilityElementInfo* elementInfo, const char* hintText); - -/** -* @brief Sets the accessibility text of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param accessibilityText Indicates the accessibility text. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoAccessibilityText(ArkUI_AccessibilityElementInfo* elementInfo, const char* accessibilityText); - -/** -* @brief Sets the accessibility description of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param accessibilityDescription Indicates the accessibility description. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoAccessibilityDescription(ArkUI_AccessibilityElementInfo* elementInfo, const char* accessibilityDescription); - -/** -* @brief Sets the child node ids of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param childCount Indicates the child count. -* @param childNodeIds Indicates the child node ids. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoChildNodeIds(ArkUI_AccessibilityElementInfo* elementInfo, int32_t childCount, int64_t* childNodeIds); - -/** -* @brief Sets the child count of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param operationActions Indicates All actions supported by the element. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoOperationActions(ArkUI_AccessibilityElementInfo* elementInfo, int32_t operationCount, ArkUI_AccessibleAction* operationActions); - -/** -* @brief Sets the screen rect of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param screenRect Indicates screen rect. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoScreenRect(ArkUI_AccessibilityElementInfo* elementInfo, ArkUI_AccessibleRect* screenRect); - -/** -* @brief Sets the checkable of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param checkable Indicates checkable. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoCheckable(ArkUI_AccessibilityElementInfo* elementInfo, bool checkable); - -/** -* @brief Sets the checked of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param checked Indicates whether the element is checked. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoChecked(ArkUI_AccessibilityElementInfo* elementInfo, bool checked); - -/** -* @brief Sets the focusable of the accessibility element information. -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param focusable Indicates whether the element is focusable. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoFocusable(ArkUI_AccessibilityElementInfo* elementInfo, bool focusable); - -/** -* @brief Sets the isFocused of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param isFocused Indicates whether the element is focused. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoFocused(ArkUI_AccessibilityElementInfo* elementInfo, bool isFocused); - -/** -* @brief Sets the isVisible of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param isVisible Indicates whether the element is visible. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoVisible(ArkUI_AccessibilityElementInfo* elementInfo, bool isVisible); - -/** -* @brief Sets the accessibilityFocused of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param accessibilityFocused Indicates whether the element is accessibility focused. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoAccessibilityFocused(ArkUI_AccessibilityElementInfo* elementInfo, bool accessibilityFocused); - -/** -* @brief Sets the selected of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param selected Indicates whether the element is selected. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoSelected(ArkUI_AccessibilityElementInfo* elementInfo, bool selected); - -/** -* @brief Sets the clickable of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param clickable Indicates whether the element is clickable. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoClickable(ArkUI_AccessibilityElementInfo* elementInfo, bool clickable); - -/** -* @brief Sets the longClickable of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param longClickable Indicates whether the element is long clickable. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoLongClickable(ArkUI_AccessibilityElementInfo* elementInfo, bool longClickable); - -/** -* @brief Sets the isEnabled of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param isEnable Indicates whether the element is enable. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoEnabled(ArkUI_AccessibilityElementInfo* elementInfo, bool isEnabled); - -/** -* @brief Sets the isPassword of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param isPassword Indicates whether the element is a password. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoIsPassword(ArkUI_AccessibilityElementInfo* elementInfo, bool isPassword); - -/** -* @brief Sets the scrollable of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param scrollable Indicates whether the element is scrollable. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoScrollable(ArkUI_AccessibilityElementInfo* elementInfo, bool scrollable); - -/** -* @brief Sets the editable of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param editable Indicates whether the element is editable. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoEditable(ArkUI_AccessibilityElementInfo* elementInfo, bool editable); - -/** -* @brief Sets the isHint of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param isHint Indicates whether the element is in the hint state. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoIsHint(ArkUI_AccessibilityElementInfo* elementInfo, bool isHint); - -/** -* @brief Sets the rangeInfo of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param rangeInfo Indicates element's range info. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoRangeInfo(ArkUI_AccessibilityElementInfo* elementInfo, ArkUI_AccessibleRangeInfo* rangeInfo); - -/** -* @brief Sets the grid of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param gridInfo Indicates element's grid info. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoGridInfo(ArkUI_AccessibilityElementInfo* elementInfo, ArkUI_AccessibleGridInfo* gridInfo); - -/** -* @brief Sets the gridItem of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param gridItem Indicates element's grid item info. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoGridItemInfo(ArkUI_AccessibilityElementInfo* elementInfo, ArkUI_AccessibleGridItemInfo* gridItem); - -/** -* @brief Sets the textBeginSelected of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param textBeginSelected Indicates the start position of the selection. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoTextBeginSelected(ArkUI_AccessibilityElementInfo* elementInfo, int32_t textBeginSelected); - -/** -* @brief Sets the textEndSelected of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param textEndSelected Indicates the end position of the selection. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoTextEndSelected(ArkUI_AccessibilityElementInfo* elementInfo, int32_t textEndSelected); - -/** -* @brief Sets the currentItemIndex of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param currentItemIndex Indicates index of the current item. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoCurrentItemIndex(ArkUI_AccessibilityElementInfo* elementInfo, int32_t currentItemIndex); - -/** -* @brief Sets the beginItemIndex of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param beginItemIndex Indicates index of the begin item. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoBeginItemIndex(ArkUI_AccessibilityElementInfo* elementInfo, int32_t beginItemIndex); - -/** -* @brief Sets the endItemIndex of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param endItemIndex Indicates index of the end item. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoEndItemIndex(ArkUI_AccessibilityElementInfo* elementInfo, int32_t endItemIndex); - -/** -* @brief Sets the itemCount of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param itemCount Indicates total number of items. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoItemCount(ArkUI_AccessibilityElementInfo* elementInfo, int32_t itemCount); - -/** -* @brief Sets the offset of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param offset Indicates pixel offset for scrolling relative to the top coordinate of the element. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoAccessibilityOffset(ArkUI_AccessibilityElementInfo* elementInfo, int32_t offset); - -/** -* @brief Sets the accessibilityGroup of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param accessibilityGroup Indicates accessibility group. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoAccessibilityGroup(ArkUI_AccessibilityElementInfo* elementInfo, bool accessibilityGroup); - -/** -* @brief Sets the accessibilityLevel of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param accessibilityLevel Indicates accessibility level. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoAccessibilityLevel(ArkUI_AccessibilityElementInfo* elementInfo, const char* accessibilityLevel); - -/** -* @brief Sets the zIndex of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param zIndex Indicates z index. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoZIndex(ArkUI_AccessibilityElementInfo* elementInfo, int32_t zIndex); - -/** -* @brief Sets the opacity of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param opacity Indicates opacity. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoAccessibilityOpacity(ArkUI_AccessibilityElementInfo* elementInfo, float opacity); - -/** -* @brief Sets the backgroundColor of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param backgroundColor Indicates background color. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoBackgroundColor(ArkUI_AccessibilityElementInfo* elementInfo, const char* backgroundColor); - -/** -* @brief Sets the backgroundImage of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param backgroundImage Indicates background image. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoBackgroundImage(ArkUI_AccessibilityElementInfo* elementInfo, const char* backgroundImage); - -/** -* @brief Sets the blur of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param blur Indicates blur. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoBlur(ArkUI_AccessibilityElementInfo* elementInfo, const char* blur); - -/** -* @brief Sets the hitTestBehavior of the accessibility element information. -* -* @param elementInfo Indicates the pointer to the accessibility element information. -* @param hitTestBehavior Indicates hitTest behavior. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityElementInfoHitTestBehavior(ArkUI_AccessibilityElementInfo* elementInfo, const char* hitTestBehavior); - -/** - * @brief Create an accessibility eventInfo. - * - * @return Returns the pointer to the accessibility event info. - * @since 13 - * @version 1.0 - */ -ArkUI_AccessibilityEventInfo* OH_ArkUI_CreateAccessibilityEventInfo(void); - -/** - * @brief Destorys an accessibility eventInfo. - * - * @param eventInfo Indicates the pointer to to the accessibility event info to be destoryed. - * @since 13 - * @version 1.0 - */ -void OH_ArkUI_DestoryAccessibilityEventInfo(ArkUI_AccessibilityEventInfo* eventInfo); - -/** -* @brief Sets the eventType of the accessibility event information. -* -* @param eventInfo Indicates the pointer to the accessibility event information. -* @param eventType Indicates event type. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityEventEventType(ArkUI_AccessibilityEventInfo* eventInfo, ArkUI_AccessibilityEventType eventType); - -/** -* @brief Sets the pageId of the accessibility event information. -* -* @param eventInfo Indicates the pointer to the accessibility event information. -* @param pageId Indicates page id. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityEventPageId(ArkUI_AccessibilityEventInfo* eventInfo, int32_t pageId); - -/** -* @brief Sets the textAnnouncedForAccessibility of the accessibility event information. -* -* @param eventInfo Indicates the pointer to the accessibility event information. -* @param textAnnouncedForAccessibility Indicates text announced for accessibility. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityEventTextAnnouncedForAccessibility(ArkUI_AccessibilityEventInfo* eventInfo, const char* textAnnouncedForAccessibility); - -/** -* @brief Sets the requestFocusId of the accessibility event information. -* -* @param eventInfo Indicates the pointer to the accessibility event information. -* @param requestFocusId Indicates ID of the request for active focus. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityEventRequestFocusId(ArkUI_AccessibilityEventInfo* eventInfo, int32_t requestFocusId); - -/** -* @brief Sets the elementInfo of the accessibility event information. -* -* @param eventInfo Indicates the pointer to the accessibility event information. -* @param elementInfo Indicates element Info. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_SetAccessibilityEventElementInfo(ArkUI_AccessibilityEventInfo* eventInfo, ArkUI_AccessibilityElementInfo* elementInfo); - -/** -* @brief Gets the value of the accessibility action argument by key. -* -* @param arguments Indicates the pointer to the accessibility action arguments. -* @param key Indicates key. -* @param value Indicates value. -* @return Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS} if success. -* Returns {@link OH_ARKUI_ACCESSIBILITY_RESULT_BAD_PARAMETER} if a parameter exception occurs. -* @since 13 -*/ -int32_t OH_ArkUI_FindAccessibilityActionArgumentByKey(ArkUI_AccessibilityActionArguments* arguments, const char* key, char* value); -#ifdef __cplusplus -}; -#endif -#endif // _NATIVE_INTERFACE_ACCESSIBILITY_H diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 21a9485aa6..205b9d2aa5 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -52,6 +52,21 @@ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateSemanticsNode( return node; } +// int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById(int64_t elementId, ArkUI_AccessibilitySearchMode mode, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { +// if(elementList == nullptr) { +// FML_DLOG(INFO) <<"OhosAccessibilityBridge::FindAccessibilityNodeInfosById elementList is null"; +// return AcessbilityErrorCode.OH_ARKUI_ACCESSIBILITY_RESULT_FAILED; +// } +// ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); +// if(elementInfo1 == nullptr) { +// FML_DLOG(INFO) <<"OhosAccessibilityBridge::FindAccessibilityNodeInfosById _elementInfo is null"; +// return AcessbilityErrorCode.OH_ARKUI_ACCESSIBILITY_RESULT_FAILED; +// } + +// } + + + /** * 从dart侧传递到c++侧的flutter语义树节点更新过程 */ @@ -68,6 +83,7 @@ void OhosAccessibilityBridge::updateSemantics( // 遍历更新的actions,并将所有的actions的id添加进actionMap for (const auto& item : actions) { const flutter::CustomAccessibilityAction action = item.second; + printTestActions(action); actions_mp_[action.id] = action; } @@ -114,9 +130,19 @@ void OhosAccessibilityBridge::updateSemantics( // } for (auto& item : update) { + // 获取当前更新的节点node const flutter::SemanticsNode& node = item.second; printTest(node); // print node struct for debugging + if(node.HasFlag(FLAGS_::kIsHidden)) { // 判断当前更新节点是隐藏的 + continue; + } + if(node.HasFlag(FLAGS_::kIsFocused)) { // 判断当前更新节点是否获焦 + + } + + + // todo:根据nodeId获取当前os对应的真实节点 // currentNode = // ArkUI_AccessibilityElementInfo::createAccessibilityElementInfo(node.id); @@ -253,25 +279,6 @@ void OhosAccessibilityBridge::updateSemantics( // kMoveCursorBackwardByWord = 1 << 20, // kSetText = 1 << 21, -int32_t convertToInt32(flutter::SemanticsAction inputAction) { - return static_cast(inputAction); -} -void OhosAccessibilityBridge::performAction(int32_t virtualViewId, - int32_t inputAction) { - // TODO 根据输入的action进行相应的响应操作 - switch (inputAction) { - case 0: - break; - case 1: - break; - case 2: - break; - // ... - default: - break; - } -} - // 获取根节点 flutter::SemanticsNode OhosAccessibilityBridge::getRootSemanticsNode() { if (flutterSemanticsTree_.size() == 0) { @@ -281,22 +288,6 @@ flutter::SemanticsNode OhosAccessibilityBridge::getRootSemanticsNode() { return flutterSemanticsTree_.at(0); } -// 找到当前焦点触发节点 -int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( - int64_t elementId, - int32_t focusType, - int32_t requestId, - int32_t elementinfo) { - return 0; -} -// 找到下一个焦点触发节点 -int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( - int64_t elementId, - int32_t direction, - int32_t requestId, - int32_t elementList) { - return 0; -} void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { @@ -318,7 +309,7 @@ void OhosAccessibilityBridge::removeSemanticsNode( } void OhosAccessibilityBridge::printTest(flutter::SemanticsNode node) { - FML_DLOG(INFO) << "=============================================="; + FML_DLOG(INFO) << "==================SemanticsNode====================="; FML_DLOG(INFO) << "node.id=" << node.id; FML_DLOG(INFO) << "node.flags=" << node.flags; FML_DLOG(INFO) << "node.actions=" << node.actions; @@ -361,8 +352,18 @@ void OhosAccessibilityBridge::printTest(flutter::SemanticsNode node) { FML_DLOG(INFO) << "node.customAccessibilityActions[" << i << "]=" << node.customAccessibilityActions[i]; } - FML_DLOG(INFO) << "=============================================="; + FML_DLOG(INFO) << "=================SemanticsNode======================"; +} + +void OhosAccessibilityBridge::printTestActions(flutter::CustomAccessibilityAction customAccessibilityAction) { + FML_DLOG(INFO) << "----------------SemanticsAction-------------------------"; + FML_DLOG(INFO) << "customAccessibilityAction.id=" << customAccessibilityAction.id; + FML_DLOG(INFO) << "customAccessibilityAction.overrideId=" << customAccessibilityAction.overrideId; + FML_DLOG(INFO) << "customAccessibilityAction.label=" << customAccessibilityAction.label; + FML_DLOG(INFO) << "customAccessibilityAction.hint=" << customAccessibilityAction.hint; + FML_DLOG(INFO) << "----------------SemanticsAction--------------------"; } + void ArkUI_AccessibilityElementInfo::createAccessibilityElementInfo(int vid) { // TODO ohos和flutter虚拟节点交互,根据虚拟节点id创建真实elementinfo // ArkUI_AccessibilityElementInfo相当于安卓的view diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 8f13d79f05..80bab7049c 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "flutter/fml/log_level.h" #include "flutter/lib/ui/semantics/custom_accessibility_action.h" @@ -51,7 +52,9 @@ class OhosAccessibilityBridge { // obtain the flutter semnatics node flutter::SemanticsNode getOrCreateSemanticsNode(int32_t id); - void performAction(int32_t virtualViewId, int32_t inputAction); + int32_t ExecuteAccessibilityAction(int64_t elementId, int64_t action, int64_t actionArguments, int32_t requestId); + + private: std::shared_ptr ax_manager_; @@ -66,17 +69,9 @@ class OhosAccessibilityBridge { std::vector flutterNavigationStack; flutter::SemanticsNode getRootSemanticsNode(); - int32_t convertToInt32(flutter::SemanticsAction inputAction); + // native os interfaces - int32_t FindFocusedAccessibilityNode(int64_t elementId, - int32_t focusType, - int32_t requestId, - int32_t elementinfo); - int32_t FindNextFocusAccessibilityNode(int64_t elementId, - int32_t direction, - int32_t requestId, - int32_t elementList); /** * Informs the TalkBack user about window name changes. @@ -95,6 +90,7 @@ class OhosAccessibilityBridge { void removeSemanticsNode(flutter::SemanticsNode nodeToBeRemoved); void printTest(flutter::SemanticsNode node); + void printTestActions(flutter::CustomAccessibilityAction customAccessibilityAction); }; class ArkUI_AccessibilityElementInfo { @@ -103,6 +99,7 @@ class ArkUI_AccessibilityElementInfo { ~ArkUI_AccessibilityElementInfo() = default; void createAccessibilityElementInfo(int vid); }; + /** struct SemanticsNode { SemanticsNode(); diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets index 458a7f175d..0b75244331 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets @@ -145,4 +145,4 @@ export const nativeSetAccessibilityFeatures: (accessibilityFeatureFlags: number, export const nativeAccessibilityStateChange: (state: Boolean) => string; -export const nativeAnnounce: (message: string) => string; \ No newline at end of file +export const nativeAnnounce: (message: string) => string; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index 38f3de9ebc..29a2fcd479 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -345,8 +345,7 @@ export default class FlutterNapi { dispatchSemanticsAction(virtualViewId: number, action: Action, responseId: number): void { if (this.isAttached()) { - // this.nativeDispatchSemanticsAction(virtualViewId, action, responseId); - // flutter. + this.nativeDispatchSemanticsAction(virtualViewId, action, responseId); } else { Log.w( TAG, diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets index 8ba4463178..22c1563ba8 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets @@ -70,6 +70,7 @@ export class FlutterAbility extends UIAbility implements Host { async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { // 冷启动通过上下文环境获取到系统当前文字大小,并进行键值存储 AppStorage.setOrCreate('fontSizeScale', this.context.config.fontSizeScale); + Log.i(TAG, "this.context.config.fontSizeScale = " + this.context.config.fontSizeScale); Log.i(TAG, "bundleCodeDir=" + this.context.bundleCodeDir); FlutterManager.getInstance().pushUIAbility(this) @@ -77,7 +78,7 @@ export class FlutterAbility extends UIAbility implements Host { this.delegate = new FlutterAbilityAndEntryDelegate(this); await this?.delegate?.onAttach(this.context); Log.i(TAG, 'onAttach end'); - this?.delegate?.platformPlugin?.setUIAbilityContext(this.context); + this?.delegate?.platformPlugin?.setUIAbilityContext(this.context); this?.delegate?.onRestoreInstanceState(want); if (this.stillAttachedForEvent("onCreate")) { -- Gitee From 203b1a0ffe936eed3b6eeda2926e5a24d2fa6e9d Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 5 Sep 2024 14:20:11 +0800 Subject: [PATCH 014/151] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E6=97=A0?= =?UTF-8?q?=E9=9A=9C=E7=A2=8Dbridge=E7=B1=BB=E9=87=8C=E7=9A=84arkui?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=EF=BC=8C=E5=B9=B6=E4=B8=8Excomponent?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=A4=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 159 ++++++++++++------ .../accessibility/ohos_accessibility_bridge.h | 132 ++------------- .../ohos_accessibility_manager.h | 9 +- .../ohos/napi/platform_view_ohos_napi.cpp | 4 +- .../platform/ohos/ohos_xcomponent_adapter.cpp | 37 +++- shell/platform/ohos/ohos_xcomponent_adapter.h | 1 + 6 files changed, 157 insertions(+), 185 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 205b9d2aa5..47d7f9871b 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" +// #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" #include "flutter/fml/logging.h" #include "ohos_accessibility_bridge.h" @@ -21,9 +21,7 @@ namespace flutter { OhosAccessibilityBridge::OhosAccessibilityBridge() { // 判断是否开启无障碍服务 - bool isAccessibilityEnabled = - this->ax_manager_->getOhosAccessibilityEnabled(); - if (isAccessibilityEnabled) { + if (isOhosAccessibilityEnabled_) { FML_DLOG(INFO) << "OhosAccessibilityBridge::OhosAccessibilityBridge " "isOhosAccessibilityEnabled = true"; } @@ -52,21 +50,99 @@ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateSemanticsNode( return node; } -// int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById(int64_t elementId, ArkUI_AccessibilitySearchMode mode, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { -// if(elementList == nullptr) { -// FML_DLOG(INFO) <<"OhosAccessibilityBridge::FindAccessibilityNodeInfosById elementList is null"; -// return AcessbilityErrorCode.OH_ARKUI_ACCESSIBILITY_RESULT_FAILED; -// } -// ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); -// if(elementInfo1 == nullptr) { -// FML_DLOG(INFO) <<"OhosAccessibilityBridge::FindAccessibilityNodeInfosById _elementInfo is null"; -// return AcessbilityErrorCode.OH_ARKUI_ACCESSIBILITY_RESULT_FAILED; -// } +/** Called to obtain element information based on a specified node. */ +int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( + int64_t elementId, + ArkUI_AccessibilitySearchMode mode, + int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList) { + if (elementList == nullptr) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::FindAccessibilityNodeInfosById " + "elementList is null"; + return OH_ARKUI_ACCESSIBILITY_RESULT_FAILED; + } + ArkUI_AccessibilityElementInfo* _elementInfo = + OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + if (_elementInfo == nullptr) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::FindAccessibilityNodeInfosById " + "_elementInfo is null"; + return OH_ARKUI_ACCESSIBILITY_RESULT_FAILED; + } -// } + //todo + + return OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS; +} + +/** Called to obtain element information based on a specified node and text + * content. */ +int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosByText( + int64_t elementId, + const char* text, + int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList) { + + return 0; +} +int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( + int64_t elementId, + ArkUI_AccessibilityFocusType focusType, + int32_t requestId, + ArkUI_AccessibilityElementInfo* elementinfo) { + return 0; +} +int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( + int64_t elementId, + ArkUI_AccessibilityFocusMoveDirection direction, + int32_t requestId, + ArkUI_AccessibilityElementInfo* elementList) { + return 0; +} +int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( + int64_t elementId, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments *actionArguments, + int32_t requestId) { + return 0; +} +int32_t OhosAccessibilityBridge::ClearFocusedFocusAccessibilityNode() { + return 0; +} +int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition(int64_t elementId, + int32_t requestId, + int32_t* index) { + return 0; +} + +void OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent(ArkUI_AccessibilityProvider* provider) { + if(provider == nullptr) { + FML_DLOG(ERROR)<<"OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent provider = null"; + return; + } + //创建eventInfo对象 + ArkUI_AccessibilityEventInfo *eventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); + if(eventInfo == nullptr) { + FML_DLOG(ERROR)<<"OH_ArkUI_CreateAccessibilityEventInfo eventInfo = null"; + return; + } + + auto callback = [](int32_t errorCode) { + if(errorCode == 0) { + FML_DLOG(ERROR)<<"OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent errorCode = 0"; + } + }; + //发送event到OH侧 + OH_ArkUI_SendAccessibilityAsyncEvent(provider, eventInfo, callback); + //销毁eventinfo + // delete eventInfo; + + FML_DLOG(ERROR)<<"OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent is succeed"; + return; +} + /** * 从dart侧传递到c++侧的flutter语义树节点更新过程 */ @@ -134,14 +210,12 @@ void OhosAccessibilityBridge::updateSemantics( const flutter::SemanticsNode& node = item.second; printTest(node); // print node struct for debugging - if(node.HasFlag(FLAGS_::kIsHidden)) { // 判断当前更新节点是隐藏的 + if (node.HasFlag(FLAGS_::kIsHidden)) { // 判断当前更新节点是隐藏的 continue; - } - if(node.HasFlag(FLAGS_::kIsFocused)) { // 判断当前更新节点是否获焦 - - } - + } + if (node.HasFlag(FLAGS_::kIsFocused)) { // 判断当前更新节点是否获焦 + } // todo:根据nodeId获取当前os对应的真实节点 // currentNode = @@ -256,28 +330,6 @@ void OhosAccessibilityBridge::updateSemantics( } } } -// kTap = 1 << 0, -// kLongPress = 1 << 1, -// kScrollLeft = 1 << 2, -// kScrollRight = 1 << 3, -// kScrollUp = 1 << 4, -// kScrollDown = 1 << 5, -// kIncrease = 1 << 6, -// kDecrease = 1 << 7, -// kShowOnScreen = 1 << 8, -// kMoveCursorForwardByCharacter = 1 << 9, -// kMoveCursorBackwardByCharacter = 1 << 10, -// kSetSelection = 1 << 11, -// kCopy = 1 << 12, -// kCut = 1 << 13, -// kPaste = 1 << 14, -// kDidGainAccessibilityFocus = 1 << 15, -// kDidLoseAccessibilityFocus = 1 << 16, -// kCustomAction = 1 << 17, -// kDismiss = 1 << 18, -// kMoveCursorForwardByWord = 1 << 19, -// kMoveCursorBackwardByWord = 1 << 20, -// kSetText = 1 << 21, // 获取根节点 flutter::SemanticsNode OhosAccessibilityBridge::getRootSemanticsNode() { @@ -288,7 +340,6 @@ flutter::SemanticsNode OhosAccessibilityBridge::getRootSemanticsNode() { return flutterSemanticsTree_.at(0); } - void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { } @@ -355,18 +406,18 @@ void OhosAccessibilityBridge::printTest(flutter::SemanticsNode node) { FML_DLOG(INFO) << "=================SemanticsNode======================"; } -void OhosAccessibilityBridge::printTestActions(flutter::CustomAccessibilityAction customAccessibilityAction) { +void OhosAccessibilityBridge::printTestActions( + flutter::CustomAccessibilityAction customAccessibilityAction) { FML_DLOG(INFO) << "----------------SemanticsAction-------------------------"; - FML_DLOG(INFO) << "customAccessibilityAction.id=" << customAccessibilityAction.id; - FML_DLOG(INFO) << "customAccessibilityAction.overrideId=" << customAccessibilityAction.overrideId; - FML_DLOG(INFO) << "customAccessibilityAction.label=" << customAccessibilityAction.label; - FML_DLOG(INFO) << "customAccessibilityAction.hint=" << customAccessibilityAction.hint; + FML_DLOG(INFO) << "customAccessibilityAction.id=" + << customAccessibilityAction.id; + FML_DLOG(INFO) << "customAccessibilityAction.overrideId=" + << customAccessibilityAction.overrideId; + FML_DLOG(INFO) << "customAccessibilityAction.label=" + << customAccessibilityAction.label; + FML_DLOG(INFO) << "customAccessibilityAction.hint=" + << customAccessibilityAction.hint; FML_DLOG(INFO) << "----------------SemanticsAction--------------------"; } -void ArkUI_AccessibilityElementInfo::createAccessibilityElementInfo(int vid) { - // TODO ohos和flutter虚拟节点交互,根据虚拟节点id创建真实elementinfo - // ArkUI_AccessibilityElementInfo相当于安卓的view -} - } // namespace flutter diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 80bab7049c..be58f04958 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -37,11 +37,10 @@ typedef flutter::SemanticsNode SEMANTICS_NODE_; * flutter和ohos的无障碍服务桥接 */ class OhosAccessibilityBridge { - private: - OhosAccessibilityBridge(); - public: + OhosAccessibilityBridge(); ~OhosAccessibilityBridge(); + bool isOhosAccessibilityEnabled_; static OhosAccessibilityBridge& GetInstance(); void announce(std::unique_ptr& message); @@ -52,16 +51,23 @@ class OhosAccessibilityBridge { // obtain the flutter semnatics node flutter::SemanticsNode getOrCreateSemanticsNode(int32_t id); - int32_t ExecuteAccessibilityAction(int64_t elementId, int64_t action, int64_t actionArguments, int32_t requestId); + int32_t FindAccessibilityNodeInfosById(int64_t elementId, ArkUI_AccessibilitySearchMode mode, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList); + int32_t FindAccessibilityNodeInfosByText(int64_t elementId, const char* text, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList); + int32_t FindFocusedAccessibilityNode(int64_t elementId, ArkUI_AccessibilityFocusType focusType, int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo); + int32_t FindNextFocusAccessibilityNode(int64_t elementId, ArkUI_AccessibilityFocusMoveDirection direction, int32_t requestId, ArkUI_AccessibilityElementInfo* elementList); + int32_t ExecuteAccessibilityAction(int64_t elementId, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments *actionArguments, int32_t requestId); + int32_t ClearFocusedFocusAccessibilityNode(); + int32_t GetAccessibilityNodeCursorPosition(int64_t elementId, int32_t requestId, int32_t* index); + void ArkUI_SendAccessibilityAsyncEvent(ArkUI_AccessibilityProvider* provider); + - private: std::shared_ptr ax_manager_; std::unordered_map flutterSemanticsTree_; std::unordered_map actions_mp_; static const int32_t ROOT_NODE_ID = 0; - int32_t previousRouteId = ROOT_NODE_ID; + // int32_t previousRouteId = ROOT_NODE_ID; // A Java/Android cached representation of the Flutter app's navigation stack. // The Flutter navigation stack is tracked so that accessibility announcements @@ -93,119 +99,5 @@ class OhosAccessibilityBridge { void printTestActions(flutter::CustomAccessibilityAction customAccessibilityAction); }; -class ArkUI_AccessibilityElementInfo { - public: - ArkUI_AccessibilityElementInfo() = default; - ~ArkUI_AccessibilityElementInfo() = default; - void createAccessibilityElementInfo(int vid); -}; - -/** -struct SemanticsNode { - SemanticsNode(); - - SemanticsNode(const SemanticsNode& other); - - ~SemanticsNode(); - - bool HasAction(SemanticsAction action) const; - bool HasFlag(SemanticsFlags flag) const; - - // Whether this node is for embedded platform views. - bool IsPlatformViewNode() const; - - int32_t id = 0; - int32_t flags = 0; - int32_t actions = 0; - int32_t maxValueLength = -1; - int32_t currentValueLength = -1; - int32_t textSelectionBase = -1; - int32_t textSelectionExtent = -1; - int32_t platformViewId = -1; - int32_t scrollChildren = 0; - int32_t scrollIndex = 0; - double scrollPosition = std::nan(""); - double scrollExtentMax = std::nan(""); - double scrollExtentMin = std::nan(""); - double elevation = 0.0; - double thickness = 0.0; - std::string label; - StringAttributes labelAttributes; - std::string hint; - StringAttributes hintAttributes; - std::string value; - StringAttributes valueAttributes; - std::string increasedValue; - StringAttributes increasedValueAttributes; - std::string decreasedValue; - StringAttributes decreasedValueAttributes; - std::string tooltip; - int32_t textDirection = 0; // 0=unknown, 1=rtl, 2=ltr - - SkRect rect = SkRect::MakeEmpty(); // Local space, relative to parent. - SkM44 transform = SkM44{}; // Identity - std::vector childrenInTraversalOrder; - std::vector childrenInHitTestOrder; - std::vector customAccessibilityActions; -}; -*/ - -/** - enum class SemanticsFlags : int32_t { - kHasCheckedState = 1 << 0, - kIsChecked = 1 << 1, - kIsSelected = 1 << 2, - kIsButton = 1 << 3, - kIsTextField = 1 << 4, - kIsFocused = 1 << 5, - kHasEnabledState = 1 << 6, - kIsEnabled = 1 << 7, - kIsInMutuallyExclusiveGroup = 1 << 8, - kIsHeader = 1 << 9, - kIsObscured = 1 << 10, - kScopesRoute = 1 << 11, - kNamesRoute = 1 << 12, - kIsHidden = 1 << 13, - kIsImage = 1 << 14, - kIsLiveRegion = 1 << 15, - kHasToggledState = 1 << 16, - kIsToggled = 1 << 17, - kHasImplicitScrolling = 1 << 18, - kIsMultiline = 1 << 19, - kIsReadOnly = 1 << 20, - kIsFocusable = 1 << 21, - kIsLink = 1 << 22, - kIsSlider = 1 << 23, - kIsKeyboardKey = 1 << 24, - kIsCheckStateMixed = 1 << 25, -}; - */ - -/** - enum class SemanticsAction : int32_t { - kTap = 1 << 0, - kLongPress = 1 << 1, - kScrollLeft = 1 << 2, - kScrollRight = 1 << 3, - kScrollUp = 1 << 4, - kScrollDown = 1 << 5, - kIncrease = 1 << 6, - kDecrease = 1 << 7, - kShowOnScreen = 1 << 8, - kMoveCursorForwardByCharacter = 1 << 9, - kMoveCursorBackwardByCharacter = 1 << 10, - kSetSelection = 1 << 11, - kCopy = 1 << 12, - kCut = 1 << 13, - kPaste = 1 << 14, - kDidGainAccessibilityFocus = 1 << 15, - kDidLoseAccessibilityFocus = 1 << 16, - kCustomAction = 1 << 17, - kDismiss = 1 << 18, - kMoveCursorForwardByWord = 1 << 19, - kMoveCursorBackwardByWord = 1 << 20, - kSetText = 1 << 21, -}; - */ } // namespace flutter #endif // OHOS_ACCESSIBILITY_BRIDGE_H diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_manager.h b/shell/platform/ohos/accessibility/ohos_accessibility_manager.h index 1e8dd7f0cd..e56df52733 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_manager.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_manager.h @@ -15,6 +15,13 @@ #ifndef OHOS_ACCESSIBILITY_MANAGER_H #define OHOS_ACCESSIBILITY_MANAGER_H +// #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" +// #include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" +// #include "types.h" +// #include "ohos_logging.h" +// #include "flutter/fml/logging.h" +// #include + // #include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" namespace flutter { @@ -31,7 +38,7 @@ class OhosAccessibilityManager { void setOhosAccessibilityEnabled(bool isEnabled); private: - bool isOhosAccessibilityEnabled_; + bool isOhosAccessibilityEnabled_ = false; }; } // namespace flutter diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index 3a442bc21e..db8b5a8433 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1848,8 +1848,8 @@ napi_value PlatformViewOHOSNapi::nativeAccessibilityStateChange( "%{public}s", (state ? "true" : "false")); // 传递到无障碍管理类 - auto ohosAccessibilityManager_ = std::make_shared(); - ohosAccessibilityManager_->setOhosAccessibilityEnabled(state); + OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge.isOhosAccessibilityEnabled_ = state; return nullptr; } diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp index ac004f2d09..3c32778024 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.cpp +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -21,6 +21,8 @@ namespace flutter { +OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); + bool g_isMouseLeftActive = false; double g_scrollDistance = 0.0; double g_resizeRate = 0.8; @@ -206,6 +208,7 @@ void OnSurfaceCreatedCB(OH_NativeXComponent* component, void* window) { for(auto it: XComponentAdapter::GetInstance()->xcomponetMap_) { if(it.second->nativeXComponent_ == component) { + LOGD("OnSurfaceCreatedCB is called"); it.second->OnSurfaceCreated(component, window); } } @@ -274,6 +277,7 @@ int32_t FindAccessibilityNodeInfosById( int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { + ohosAccessibilityBridge.FindAccessibilityNodeInfosById(elementId, mode, requestId, elementList); LOGD("accessibilityProviderCallback_.FindAccessibilityNodeInfosById"); return 0; } @@ -285,16 +289,17 @@ int32_t FindAccessibilityNodeInfosByText( int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { + ohosAccessibilityBridge.FindAccessibilityNodeInfosByText(elementId, text, requestId, elementList); LOGD("accessibilityProviderCallback_.FindAccessibilityNodeInfosByText"); return 0; } /** Called when need to get the focused element info based on a specified node. */ int32_t FindFocusedAccessibilityNode( - int64_t elementId, - ArkUI_AccessibilityFocusType focusType, - int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo) +int64_t elementId, ArkUI_AccessibilityFocusType focusType, +int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo) { + ohosAccessibilityBridge.FindFocusedAccessibilityNode(elementId, focusType, requestId, elementinfo); LOGD("accessibilityProviderCallback_.FindFocusedAccessibilityNode"); return 0; } @@ -304,8 +309,9 @@ int32_t FindNextFocusAccessibilityNode( int64_t elementId, ArkUI_AccessibilityFocusMoveDirection direction, int32_t requestId, - ArkUI_AccessibilityElementInfo* elementList) + ArkUI_AccessibilityElementInfo *elementList) { + ohosAccessibilityBridge.FindNextFocusAccessibilityNode(elementId, direction, requestId, elementList); LOGD("accessibilityProviderCallback_.FindNextFocusAccessibilityNode"); return 0; } @@ -314,9 +320,10 @@ int32_t FindNextFocusAccessibilityNode( int32_t ExecuteAccessibilityAction( int64_t elementId, ArkUI_Accessibility_ActionType action, - ArkUI_AccessibilityActionArguments *actionArguments, + ArkUI_AccessibilityActionArguments* actionArguments, int32_t requestId) { + ohosAccessibilityBridge.ExecuteAccessibilityAction(elementId, action, actionArguments, requestId); LOGD("accessibilityProviderCallback_.ExecuteAccessibilityAction"); return 0; } @@ -334,6 +341,7 @@ int32_t GetAccessibilityNodeCursorPosition( int32_t requestId, int32_t* index) { + ohosAccessibilityBridge.GetAccessibilityNodeCursorPosition(elementId, requestId, index); LOGD("accessibilityProviderCallback_.GetAccessibilityNodeCursorPosition"); return 0; } @@ -389,10 +397,23 @@ void XComponentBase::SetNativeXComponent(OH_NativeXComponent* nativeXComponent){ BindXComponentCallback(); OH_NativeXComponent_RegisterCallback(nativeXComponent_, &callback_); OH_NativeXComponent_RegisterMouseEventCallback(nativeXComponent_, &mouseCallback_); + BindAccessibilityProviderCallback(); - ArkUI_AccessibilityProvider *accessibilityProvider = nullptr; - OH_NativeXComponent_GetNativeAccessibilityProvider(nativeXComponent, &accessibilityProvider); - OH_ArkUI_AccessibilityProviderRegisterCallback(accessibilityProvider, &accessibilityProviderCallback_); + ArkUI_AccessibilityProvider* accessibilityProvider = nullptr; + int32_t ret1 = OH_NativeXComponent_GetNativeAccessibilityProvider(nativeXComponent_, &accessibilityProvider); + if(ret1 != 0) { + LOGE("OH_NativeXComponent_GetNativeAccessibilityProvider is failed"); + return; + } + int32_t ret2 = OH_ArkUI_AccessibilityProviderRegisterCallback(accessibilityProvider, &accessibilityProviderCallback_); + if(ret2 != 0) { + LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is failed"); + return; + } + LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is %{public}d", ret2); + // ohosAccessibilityBridge.ArkUI_SendAccessibilityAsyncEvent(accessibilityProvider); + LOGI("XComponentBase::SetNativeXComponent OH_ArkUI_AccessibilityProviderRegisterCallback is succeed"); + } } diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.h b/shell/platform/ohos/ohos_xcomponent_adapter.h index 821a203c9b..d5accff83a 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.h +++ b/shell/platform/ohos/ohos_xcomponent_adapter.h @@ -23,6 +23,7 @@ #include "napi/native_api.h" #include "napi_common.h" #include +#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" namespace flutter { class XComponentBase -- Gitee From d17090d4b568f9797e3e3738cb43fcdb491e90b2 Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 5 Sep 2024 21:26:12 +0800 Subject: [PATCH 015/151] =?UTF-8?q?feat:=E5=AE=8C=E5=96=84=E6=97=A0?= =?UTF-8?q?=E9=9A=9C=E7=A2=8Dbridge=E7=9A=84=E8=AF=AD=E4=B9=89=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E7=AE=97=E6=B3=95=E6=B5=81=E7=A8=8B=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0findaccessibilityinfosbyid=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E4=BA=A4=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 108 +++++++++++++++--- .../accessibility/ohos_accessibility_bridge.h | 7 +- .../ohos/napi/platform_view_ohos_napi.cpp | 3 +- .../ohos/napi/platform_view_ohos_napi.h | 3 +- .../platform/ohos/ohos_xcomponent_adapter.cpp | 7 +- shell/platform/ohos/platform_view_ohos.cpp | 12 +- .../ohos/platform_view_ohos_delegate.h | 2 +- 7 files changed, 115 insertions(+), 27 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 47d7f9871b..9ee87a8be0 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -20,6 +20,7 @@ namespace flutter { OhosAccessibilityBridge::OhosAccessibilityBridge() { + // 判断是否开启无障碍服务 if (isOhosAccessibilityEnabled_) { FML_DLOG(INFO) << "OhosAccessibilityBridge::OhosAccessibilityBridge " @@ -36,6 +37,19 @@ OhosAccessibilityBridge& OhosAccessibilityBridge::GetInstance() { void OhosAccessibilityBridge::announce(std::unique_ptr& message) { FML_DLOG(INFO) << ("Native C++ OhosAccessibilityBridge::announce message: ") << (message.get()); + //创建并设置屏幕朗读事件 + ArkUI_AccessibilityEventInfo* announceEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); + int32_t ret1 = OH_ArkUI_SetAccessibilityEventEventType(announceEventInfo, ArkUI_AccessibilityEventType::ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_ANNOUNCE_FOR_ACCESSIBILITY); + if(ret1 != 0) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::announce OH_ArkUI_AccessibilityEventSetEventType failed"; + return; + } + int32_t ret2 = OH_ArkUI_SetAccessibilityEventTextAnnouncedForAccessibility(announceEventInfo, message.get()); + if(ret2 != 0) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::announce OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility failed"; + return; + } + return; } @@ -49,8 +63,45 @@ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateSemanticsNode( } return node; } +/** + * flutter初始化配置给arkui创建的elementInfo + */ +void OhosAccessibilityBridge::flutterInitElementInfo(ArkUI_AccessibilityElementInfo* elementInfo) { + if(elementInfo == nullptr) { + FML_DLOG(ERROR)<<"OhosAccessibilityBridge::flutterInitElementInfo -> elementInfo = nullptr"; + } + if(!flutterSemanticsTree_.size()) { + FML_DLOG(ERROR)<<"OhosAccessibilityBridge::flutterInitElementInfo flutterSemanticsTree_.size() = 0"; + return; + } + //将flutter语义节点树传递给arkui的无障碍elementinfo + for(const auto& item: flutterSemanticsTree_) { + SEMANTICS_NODE_ flutterNode = item.second; + OH_ArkUI_SetAccessibilityElementInfoElementId(elementInfo, flutterNode.id); + OH_ArkUI_SetAccessibilityElementInfoAccessibilityText(elementInfo, flutterNode.label.c_str()); + + int32_t childCount = static_cast(flutterNode.childrenInTraversalOrder.size()); + int64_t childNodeIds[childCount]; + for(int32_t i=0; i(flutterNode.childrenInTraversalOrder[i]); + } + OH_ArkUI_SetAccessibilityElementInfoChildNodeIds(elementInfo, childCount, childNodeIds); + + // force to true for debugging + OH_ArkUI_SetAccessibilityElementInfoFocusable(elementInfo, true); + OH_ArkUI_SetAccessibilityElementInfoFocused(elementInfo, true); + OH_ArkUI_SetAccessibilityElementInfoVisible(elementInfo, true); + OH_ArkUI_SetAccessibilityElementInfoAccessibilityFocused(elementInfo, true); + OH_ArkUI_SetAccessibilityElementInfoSelected(elementInfo, true); + OH_ArkUI_SetAccessibilityElementInfoEnabled(elementInfo, true); + } +} -/** Called to obtain element information based on a specified node. */ +/** + * Called to obtain element information based on a specified node. + * NOTE: 该arkui接口需要在系统无障碍服务开启时,才能触发调用 + * TODO: 当前实现版本为实现简易功能,仅对flutter语义focused节点进行交互,后续完善并优化 + */ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( int64_t elementId, ArkUI_AccessibilitySearchMode mode, @@ -61,19 +112,32 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( "elementList is null"; return OH_ARKUI_ACCESSIBILITY_RESULT_FAILED; } - ArkUI_AccessibilityElementInfo* _elementInfo = + //创建elementinfo + ArkUI_AccessibilityElementInfo* focusedElementInfo = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); - if (_elementInfo == nullptr) { + if (focusedElementInfo == nullptr) { FML_DLOG(INFO) << "OhosAccessibilityBridge::FindAccessibilityNodeInfosById " - "_elementInfo is null"; + "elementInfo is null"; return OH_ARKUI_ACCESSIBILITY_RESULT_FAILED; } - //todo - - - - + /** Search for current nodes. */ + if(mode == ArkUI_AccessibilitySearchMode::NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { + flutterInitElementInfo(focusedElementInfo); + } else if(ArkUI_AccessibilitySearchMode::NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS) { + /** Search for parent nodes. */ + flutterInitElementInfo(focusedElementInfo); + } else if(ArkUI_AccessibilitySearchMode::NATIVE_SEARCH_MODE_PREFETCH_SIBLINGS) { + /** Search for sibling nodes. */ + flutterInitElementInfo(focusedElementInfo); + } else if(ArkUI_AccessibilitySearchMode::NATIVE_SEARCH_MODE_PREFETCH_CHILDREN) { + /** Search for child nodes at the next level. */ + flutterInitElementInfo(focusedElementInfo); + } else { //ArkUI_AccessibilitySearchMode::NATIVE_SEARCH_MODE_PREFETCH_RECURSIVE_CHILDREN + /** Search for all child nodes. */ + flutterInitElementInfo(focusedElementInfo); + } + FML_DLOG(INFO) << "OhosAccessibilityBridge::FindAccessibilityNodeInfosById is succeed!"; return OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS; } @@ -92,6 +156,8 @@ int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( ArkUI_AccessibilityFocusType focusType, int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo) { + //todo ... + return 0; } int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( @@ -99,6 +165,8 @@ int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( ArkUI_AccessibilityFocusMoveDirection direction, int32_t requestId, ArkUI_AccessibilityElementInfo* elementList) { + //todo ... + return 0; } int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( @@ -106,14 +174,19 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments *actionArguments, int32_t requestId) { + //todo ... + return 0; } int32_t OhosAccessibilityBridge::ClearFocusedFocusAccessibilityNode() { + //todo ... + return 0; } int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition(int64_t elementId, int32_t requestId, int32_t* index) { + //todo ... return 0; } @@ -128,7 +201,6 @@ void OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent(ArkUI_Accessibil FML_DLOG(ERROR)<<"OH_ArkUI_CreateAccessibilityEventInfo eventInfo = null"; return; } - auto callback = [](int32_t errorCode) { if(errorCode == 0) { FML_DLOG(ERROR)<<"OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent errorCode = 0"; @@ -136,13 +208,12 @@ void OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent(ArkUI_Accessibil }; //发送event到OH侧 OH_ArkUI_SendAccessibilityAsyncEvent(provider, eventInfo, callback); - //销毁eventinfo - // delete eventInfo; FML_DLOG(ERROR)<<"OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent is succeed"; return; } + /** * 从dart侧传递到c++侧的flutter语义树节点更新过程 */ @@ -214,6 +285,11 @@ void OhosAccessibilityBridge::updateSemantics( continue; } if (node.HasFlag(FLAGS_::kIsFocused)) { // 判断当前更新节点是否获焦 + FML_DLOG(INFO) <<"OhosAccessibilityBridge::updateSemantics node.HasFlag(FLAGS_::kIsFocused) node.id="< flutterSemanticsTree_.size()=0"; return flutter::SemanticsNode{}; } return flutterSemanticsTree_.at(0); @@ -346,6 +422,10 @@ void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { void OhosAccessibilityBridge::removeSemanticsNode( flutter::SemanticsNode nodeToBeRemoved) { + if(!flutterSemanticsTree_.size()) { + FML_DLOG(ERROR)<<"OhosAccessibilityBridge::removeSemanticsNode -> flutterSemanticsTree_.szie()=0"; + return; + } if (flutterSemanticsTree_.find(nodeToBeRemoved.id) == flutterSemanticsTree_.end()) { FML_DLOG(INFO) << "Attempted to remove a node that is not in the tree."; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index be58f04958..4206f4143c 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -40,7 +40,7 @@ class OhosAccessibilityBridge { public: OhosAccessibilityBridge(); ~OhosAccessibilityBridge(); - bool isOhosAccessibilityEnabled_; + bool isOhosAccessibilityEnabled_; static OhosAccessibilityBridge& GetInstance(); void announce(std::unique_ptr& message); @@ -60,11 +60,10 @@ class OhosAccessibilityBridge { int32_t GetAccessibilityNodeCursorPosition(int64_t elementId, int32_t requestId, int32_t* index); void ArkUI_SendAccessibilityAsyncEvent(ArkUI_AccessibilityProvider* provider); - - private: std::shared_ptr ax_manager_; std::unordered_map flutterSemanticsTree_; + std::vector flutterSemanticsTreeVec; std::unordered_map actions_mp_; static const int32_t ROOT_NODE_ID = 0; // int32_t previousRouteId = ROOT_NODE_ID; @@ -74,6 +73,8 @@ class OhosAccessibilityBridge { // can be made during Flutter's navigation changes. std::vector flutterNavigationStack; + void flutterInitElementInfo(ArkUI_AccessibilityElementInfo* elementInfo); + flutter::SemanticsNode getRootSemanticsNode(); diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index db8b5a8433..74dac221e9 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1856,7 +1856,6 @@ napi_value PlatformViewOHOSNapi::nativeAccessibilityStateChange( napi_value PlatformViewOHOSNapi::nativeAnnounce( napi_env env, napi_callback_info info) { - size_t argc = 1; napi_value args[1] = {nullptr}; napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); @@ -1868,7 +1867,7 @@ napi_value PlatformViewOHOSNapi::nativeAnnounce( auto char_array = std::make_unique(null_terminated_length); napi_get_value_string_utf8(env, args[0], char_array.get(), null_terminated_length, nullptr); - LOGD("1535 PlatformViewOHOSNapi::nativeAnnounce message: %{public}s", char_array.get()); + LOGD("PlatformViewOHOSNapi::nativeAnnounce message: %{public}s", char_array.get()); OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge.announce(char_array); return nullptr; diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h index c5712fd93d..844b140bdf 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.h +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -197,7 +197,7 @@ class PlatformViewOHOSNapi { static napi_value nativeDecodeUtf8(napi_env env, napi_callback_info info); /** - * debug --> ets call c++ + * ets call c++ */ static napi_value nativeUpdateSemantics(napi_env env, napi_callback_info info); @@ -216,7 +216,6 @@ class PlatformViewOHOSNapi { napi_ref ref_napi_obj_; static std::vector system_languages; fml::RefPtr platform_task_runner_; - std::shared_ptr ohosAccessibilityManager_; }; } // namespace flutter diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp index 3c32778024..c1d1eed184 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.cpp +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -21,7 +21,6 @@ namespace flutter { -OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); bool g_isMouseLeftActive = false; double g_scrollDistance = 0.0; @@ -277,6 +276,7 @@ int32_t FindAccessibilityNodeInfosById( int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { + OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge.FindAccessibilityNodeInfosById(elementId, mode, requestId, elementList); LOGD("accessibilityProviderCallback_.FindAccessibilityNodeInfosById"); return 0; @@ -289,6 +289,7 @@ int32_t FindAccessibilityNodeInfosByText( int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { + OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge.FindAccessibilityNodeInfosByText(elementId, text, requestId, elementList); LOGD("accessibilityProviderCallback_.FindAccessibilityNodeInfosByText"); return 0; @@ -299,6 +300,7 @@ int32_t FindFocusedAccessibilityNode( int64_t elementId, ArkUI_AccessibilityFocusType focusType, int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo) { + OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge.FindFocusedAccessibilityNode(elementId, focusType, requestId, elementinfo); LOGD("accessibilityProviderCallback_.FindFocusedAccessibilityNode"); return 0; @@ -311,6 +313,7 @@ int32_t FindNextFocusAccessibilityNode( int32_t requestId, ArkUI_AccessibilityElementInfo *elementList) { + OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge.FindNextFocusAccessibilityNode(elementId, direction, requestId, elementList); LOGD("accessibilityProviderCallback_.FindNextFocusAccessibilityNode"); return 0; @@ -323,6 +326,7 @@ int32_t ExecuteAccessibilityAction( ArkUI_AccessibilityActionArguments* actionArguments, int32_t requestId) { + OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge.ExecuteAccessibilityAction(elementId, action, actionArguments, requestId); LOGD("accessibilityProviderCallback_.ExecuteAccessibilityAction"); return 0; @@ -341,6 +345,7 @@ int32_t GetAccessibilityNodeCursorPosition( int32_t requestId, int32_t* index) { + OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge.GetAccessibilityNodeCursorPosition(elementId, requestId, index); LOGD("accessibilityProviderCallback_.GetAccessibilityNodeCursorPosition"); return 0; diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index 1af47e8786..3e8a08a81e 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -109,6 +109,9 @@ PlatformViewOHOS::PlatformViewOHOS( LOGI("ohos_surface_ end 2"); ohos_surface_ = surface_factory_->CreateSurface(); LOGI("ohos_surface_ end 3"); + + ax_bridge_delegate_ = std::make_shared(); + FML_CHECK(ohos_surface_ && ohos_surface_->IsValid()) << "Could not create an OpenGL, Vulkan or Software surface to set " "up " @@ -292,13 +295,14 @@ void PlatformViewOHOS::UpdateAssetResolverByType( delegate_.UpdateAssetResolverByType(std::move(updated_asset_resolver), type); } -// todo accessbility_bridges +// ohos_accessbility_bridge void PlatformViewOHOS::UpdateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { - FML_DLOG(INFO) << "PlatformViewOHOS::UpdateSemantics"; - // platform_view_ohos_delegate_->UpdateSemantics(update, actions); - ax_bridge_delegate_->updateSemantics(update, actions); + FML_DLOG(INFO) << "PlatformViewOHOS::UpdateSemantics is called"; + if(ax_bridge_delegate_) { + ax_bridge_delegate_->updateSemantics(update, actions); + } } // |PlatformView| diff --git a/shell/platform/ohos/platform_view_ohos_delegate.h b/shell/platform/ohos/platform_view_ohos_delegate.h index 97f5d826fc..7ad56818c0 100644 --- a/shell/platform/ohos/platform_view_ohos_delegate.h +++ b/shell/platform/ohos/platform_view_ohos_delegate.h @@ -40,7 +40,7 @@ class PlatformViewOHOSDelegate { private: const std::shared_ptr napi_facade_; - const std::shared_ptr ax_bridge_router_; + }; } // namespace flutter #endif \ No newline at end of file -- Gitee From 1b8564006bbd51807ee9d2a9e056e3084501afa5 Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 5 Sep 2024 21:28:42 +0800 Subject: [PATCH 016/151] =?UTF-8?q?fix:=E5=88=A0=E9=99=A4=E6=97=A0?= =?UTF-8?q?=E9=9A=9C=E7=A2=8Dbridge=E6=9E=84=E9=80=A0=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E9=87=8C=E7=9A=84debug=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos/accessibility/ohos_accessibility_bridge.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 9ee87a8be0..44fe537f40 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -19,14 +19,7 @@ namespace flutter { -OhosAccessibilityBridge::OhosAccessibilityBridge() { - - // 判断是否开启无障碍服务 - if (isOhosAccessibilityEnabled_) { - FML_DLOG(INFO) << "OhosAccessibilityBridge::OhosAccessibilityBridge " - "isOhosAccessibilityEnabled = true"; - } -} +OhosAccessibilityBridge::OhosAccessibilityBridge() {}; OhosAccessibilityBridge::~OhosAccessibilityBridge() {}; OhosAccessibilityBridge& OhosAccessibilityBridge::GetInstance() { -- Gitee From 312240a3b9195ddedc627e88ab6311a8d2a4df60 Mon Sep 17 00:00:00 2001 From: liujiake Date: Thu, 5 Sep 2024 22:01:24 +0800 Subject: [PATCH 017/151] =?UTF-8?q?OhosAccessibilityBridge=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E4=BD=BF=E7=94=A8=E5=8D=95=E4=BE=8B=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- .../ohos_accessibility_bridge.cpp | 4 +-- .../ets/embedding/engine/FlutterEngine.ets | 27 +------------------ shell/platform/ohos/platform_view_ohos.cpp | 6 ++--- shell/platform/ohos/platform_view_ohos.h | 2 +- 4 files changed, 6 insertions(+), 33 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 44fe537f40..94024cfbab 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -19,8 +19,8 @@ namespace flutter { -OhosAccessibilityBridge::OhosAccessibilityBridge() {}; -OhosAccessibilityBridge::~OhosAccessibilityBridge() {}; +OhosAccessibilityBridge::OhosAccessibilityBridge() = default; +OhosAccessibilityBridge::~OhosAccessibilityBridge() = default; OhosAccessibilityBridge& OhosAccessibilityBridge::GetInstance() { static OhosAccessibilityBridge ohosAccessibilityBridge; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterEngine.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterEngine.ets index db8dd00969..cd3cd81923 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterEngine.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterEngine.ets @@ -34,12 +34,11 @@ import SystemChannel from './systemchannels/SystemChannel'; import MouseCursorChannel from './systemchannels/MouseCursorChannel'; import RestorationChannel from './systemchannels/RestorationChannel'; import LocalizationChannel from './systemchannels/LocalizationChannel'; -import AccessibilityChannel, { AccessibilityMessageHandler } from './systemchannels/AccessibilityChannel'; +import AccessibilityChannel from './systemchannels/AccessibilityChannel'; import LocalizationPlugin from '../../plugin/localization/LocalizationPlugin' import SettingsChannel from './systemchannels/SettingsChannel'; import PlatformViewsController from '../../plugin/platform/PlatformViewsController'; import { FlutterRenderer } from './renderer/FlutterRenderer'; -import { ByteBuffer } from '../../util/ByteBuffer'; const TAG = "FlutterEngine"; @@ -124,7 +123,6 @@ export default class FlutterEngine implements EngineLifecycleListener{ this.localeChannel = new LocalizationChannel(this.dartExecutor); this.accessibilityChannel = new AccessibilityChannel(this.dartExecutor, this.flutterNapi); - this.accessibilityChannel.setAccessibilityMessageHandler(new AccessibilityMessageHandlerImp()); this.flutterNapi.addEngineLifecycleListener(this); this.localizationPlugin = new LocalizationPlugin(context, this.localeChannel); @@ -290,27 +288,4 @@ export interface EngineLifecycleListener { onPreEngineRestart(): void; onEngineWillDestroy(): void; -} -export class AccessibilityMessageHandlerImp implements AccessibilityMessageHandler { - announce(message: string): void { - Log.d(TAG, "handler announce."); - } - onTap(nodeId: number): void { - Log.d(TAG, "handler onTap."); - } - onLongPress(nodeId: number): void { - Log.d(TAG, "handler onLongPress."); - } - onTooltip(nodeId: string): void { - Log.d(TAG, "handler onTooltip."); - } - updateSemantics(buffer: ByteBuffer, strings: string[], stringAttributeArgs: ByteBuffer[]): void { - Log.d(TAG, "handler updateSemantics"); - } - updateCustomAccessibilityActions(buffer: ByteBuffer, strings: string[]): void { - Log.d(TAG, "handler updateCustomAccessibilityActions"); - } - accessibilityStateChange(state: Boolean): void{ - Log.d(TAG, "handler accessibilityStateChange"); - } } \ No newline at end of file diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index 3e8a08a81e..6b588641aa 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -110,7 +110,7 @@ PlatformViewOHOS::PlatformViewOHOS( ohos_surface_ = surface_factory_->CreateSurface(); LOGI("ohos_surface_ end 3"); - ax_bridge_delegate_ = std::make_shared(); + ax_bridge_delegate_ = OhosAccessibilityBridge::GetInstance(); FML_CHECK(ohos_surface_ && ohos_surface_->IsValid()) << "Could not create an OpenGL, Vulkan or Software surface to set " @@ -300,9 +300,7 @@ void PlatformViewOHOS::UpdateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { FML_DLOG(INFO) << "PlatformViewOHOS::UpdateSemantics is called"; - if(ax_bridge_delegate_) { - ax_bridge_delegate_->updateSemantics(update, actions); - } + ax_bridge_delegate_.updateSemantics(update, actions); } // |PlatformView| diff --git a/shell/platform/ohos/platform_view_ohos.h b/shell/platform/ohos/platform_view_ohos.h index 56916b705c..3fc4d815d1 100644 --- a/shell/platform/ohos/platform_view_ohos.h +++ b/shell/platform/ohos/platform_view_ohos.h @@ -142,7 +142,7 @@ class PlatformViewOHOS final : public PlatformView { std::map contextDatas_; std::shared_ptr platform_view_ohos_delegate_; - std::shared_ptr ax_bridge_delegate_; + OhosAccessibilityBridge ax_bridge_delegate_; static bool isDestroyed_; static pthread_mutex_t mutex_; -- Gitee From 0c6867af4328b63260e13a51601016090dfdb2d8 Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 6 Sep 2024 16:46:45 +0800 Subject: [PATCH 018/151] =?UTF-8?q?feat:=E5=AE=8C=E5=96=84flutter=E8=AF=AD?= =?UTF-8?q?=E4=B9=89=E6=A0=91=E8=BD=AC=E5=8C=96=E4=B8=BAarkui=E8=AF=AD?= =?UTF-8?q?=E4=B9=89=E6=A0=91=E7=9A=84=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0updatesemantics=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 226 +++++++++++++----- .../accessibility/ohos_accessibility_bridge.h | 10 +- 2 files changed, 179 insertions(+), 57 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 94024cfbab..bb8a6d8f6c 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -// #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" +#include #include "flutter/fml/logging.h" #include "ohos_accessibility_bridge.h" @@ -28,8 +28,6 @@ OhosAccessibilityBridge& OhosAccessibilityBridge::GetInstance() { } void OhosAccessibilityBridge::announce(std::unique_ptr& message) { - FML_DLOG(INFO) << ("Native C++ OhosAccessibilityBridge::announce message: ") - << (message.get()); //创建并设置屏幕朗读事件 ArkUI_AccessibilityEventInfo* announceEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); int32_t ret1 = OH_ArkUI_SetAccessibilityEventEventType(announceEventInfo, ArkUI_AccessibilityEventType::ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_ANNOUNCE_FOR_ACCESSIBILITY); @@ -42,54 +40,156 @@ void OhosAccessibilityBridge::announce(std::unique_ptr& message) { FML_DLOG(INFO) << "OhosAccessibilityBridge::announce OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility failed"; return; } - + FML_DLOG(INFO) << ("OhosAccessibilityBridge::announce message: ") + << (message.get()); return; } -flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateSemanticsNode( +/** + * 根据nodeid获取或创建flutter语义节点 + */ +flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode( int32_t id) { flutter::SemanticsNode node; - if (flutterSemanticsTree_.find(id) != flutterSemanticsTree_.end()) { + if (flutterSemanticsTree_.count(id) > 0) { node = flutterSemanticsTree_.at(id); } else { - flutterSemanticsTree_[id] = node; + flutterSemanticsTree_.insert({id, node}); + FML_DLOG(INFO)<<"OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode insert new flutterNode"; } return node; } + /** - * flutter初始化配置给arkui创建的elementInfo + * flutter的语义节点初始化配置给arkui创建的elementInfos */ -void OhosAccessibilityBridge::flutterInitElementInfo(ArkUI_AccessibilityElementInfo* elementInfo) { - if(elementInfo == nullptr) { - FML_DLOG(ERROR)<<"OhosAccessibilityBridge::flutterInitElementInfo -> elementInfo = nullptr"; - } +void OhosAccessibilityBridge::flutterSemanticsNodesToElementInfos() { if(!flutterSemanticsTree_.size()) { - FML_DLOG(ERROR)<<"OhosAccessibilityBridge::flutterInitElementInfo flutterSemanticsTree_.size() = 0"; + FML_DLOG(ERROR)<<"OhosAccessibilityBridge::flutterSemanticsNodesToElementInfos flutterSemanticsTree_.size() = 0"; return; } //将flutter语义节点树传递给arkui的无障碍elementinfo for(const auto& item: flutterSemanticsTree_) { SEMANTICS_NODE_ flutterNode = item.second; + + //创建elementinfo,系统自动加入到elementinfolist + ArkUI_AccessibilityElementInfo* elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); + if (elementInfo == nullptr) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::flutterSemanticsNodesToElementInfos " + "elementInfo is null"; + return; + } + /** + * FIXME: 这里先不统一将所有的elementinfos的全部属性进行配置,预先配置一些必要信息比如:id + * 而是使用Flutter_InitSpercificElementInfoById对特定节点进行配置 + * */ OH_ArkUI_SetAccessibilityElementInfoElementId(elementInfo, flutterNode.id); - OH_ArkUI_SetAccessibilityElementInfoAccessibilityText(elementInfo, flutterNode.label.c_str()); + //将当前flutter节点的全部子节点,创建每一个对应的childelementinfos并进行必要配置 int32_t childCount = static_cast(flutterNode.childrenInTraversalOrder.size()); - int64_t childNodeIds[childCount]; for(int32_t i=0; i(flutterNode.childrenInTraversalOrder[i]); + int32_t childId = flutterNode.childrenInTraversalOrder[i]; + + //加入父子节点id映射 <父节点id,子节点id> + parentChildIdMap.insert({flutterNode.id, childId}); + + ArkUI_AccessibilityElementInfo* childElementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); + if (childElementInfo == nullptr) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::flutterSemanticsNodesToElementInfos " + "childElementInfo[" + std::to_string(i) + "] is null"; + return; + } + OH_ArkUI_SetAccessibilityElementInfoElementId(childElementInfo, childId); } - OH_ArkUI_SetAccessibilityElementInfoChildNodeIds(elementInfo, childCount, childNodeIds); - - // force to true for debugging - OH_ArkUI_SetAccessibilityElementInfoFocusable(elementInfo, true); - OH_ArkUI_SetAccessibilityElementInfoFocused(elementInfo, true); - OH_ArkUI_SetAccessibilityElementInfoVisible(elementInfo, true); - OH_ArkUI_SetAccessibilityElementInfoAccessibilityFocused(elementInfo, true); - OH_ArkUI_SetAccessibilityElementInfoSelected(elementInfo, true); - OH_ArkUI_SetAccessibilityElementInfoEnabled(elementInfo, true); } } +/** + * 获取当前elementid的父节点id + */ +int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) { + int32_t childElementId = static_cast(elementId); + if(!parentChildIdMap.size()) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::GetParentId parentChildIdMap.size()=0"; + return -2; + } + for(const auto& item: parentChildIdMap) { + if(item.second == childElementId) { + return item.first; + } + } + return -1; +} + +/** + * 在flutter引擎里实现对特定id的elementinfo的节点属性配置 + */ +void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId) { + if(elementInfoFromList == nullptr) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById " + "elementInfoFromList is null"; + return; + } + //根据elementid获取对应的flutter节点 + SEMANTICS_NODE_ flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); + + //根据flutternode信息配置对应的elementinfo + OH_ArkUI_SetAccessibilityElementInfoElementId(elementInfoFromList, flutterNode.id); + //设置父节点id + int32_t parentId = GetParentId(elementId); + if(parentId < 0) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById " + "GetParentId is null"; + return; + } + OH_ArkUI_SetAccessibilityElementInfoParentId(elementInfoFromList, parentId); + //设置无障碍播报文本 + OH_ArkUI_SetAccessibilityElementInfoAccessibilityText(elementInfoFromList, flutterNode.label.c_str()); + + //配置child节点信息 + int32_t childCount = static_cast(flutterNode.childrenInTraversalOrder.size()); + int64_t childNodeIds[childCount]; + for(int32_t i=0; i(flutterNode.childrenInTraversalOrder[i]); + } + OH_ArkUI_SetAccessibilityElementInfoChildNodeIds(elementInfoFromList, childCount, childNodeIds); + + // 配置常用属性,force to true for debugging + OH_ArkUI_SetAccessibilityElementInfoFocusable(elementInfoFromList, true); + OH_ArkUI_SetAccessibilityElementInfoFocused(elementInfoFromList, true); + OH_ArkUI_SetAccessibilityElementInfoVisible(elementInfoFromList, true); + OH_ArkUI_SetAccessibilityElementInfoAccessibilityFocused(elementInfoFromList, true); + OH_ArkUI_SetAccessibilityElementInfoSelected(elementInfoFromList, true); + OH_ArkUI_SetAccessibilityElementInfoEnabled(elementInfoFromList, true); + + //设置elementinfo的屏幕坐标范围 + int32_t left = static_cast(flutterNode.rect.fLeft); + int32_t top = static_cast(flutterNode.rect.fTop); + int32_t right = static_cast(flutterNode.rect.fRight); + int32_t bottom = static_cast(flutterNode.rect.fBottom); + ArkUI_AccessibleRect rect = {left, top, right, bottom}; + OH_ArkUI_SetAccessibilityElementInfoScreenRect(elementInfoFromList, &rect); + + //无障碍重要性,用于控制某个组件是否可被无障碍辅助服务所识别。支持的值为: + // “auto”:根据组件不同会转换为“yes”或者“no”。 + // “yes”:当前组件可被无障碍辅助服务所识别。 + // “no”:当前组件不可被无障碍辅助服务所识别。 + // “no-hide-descendants”:当前组件及其所有子组件不可被无障碍辅助服务所识别。 + // 默认值:“auto” + OH_ArkUI_SetAccessibilityElementInfoAccessibilityLevel(elementInfoFromList, "yes"); + //无障碍组,设置为true时表示该组件及其所有子组件为一整个可以选中的组件,无障碍服务将不再关注其子组件内容。默认值:false + OH_ArkUI_SetAccessibilityElementInfoAccessibilityGroup(elementInfoFromList, false); + + //设置elementinfo的action类型 + int32_t actionTypeNum = 2; + ArkUI_AccessibleAction actions[actionTypeNum]; + actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS; + actions[0].description = "flutter-ohos"; + actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_CLICK; + actions[1].description = "flutter-ohos"; + OH_ArkUI_SetAccessibilityElementInfoOperationActions(elementInfoFromList, actionTypeNum, actions); +} + /** * Called to obtain element information based on a specified node. * NOTE: 该arkui接口需要在系统无障碍服务开启时,才能触发调用 @@ -105,31 +205,41 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( "elementList is null"; return OH_ARKUI_ACCESSIBILITY_RESULT_FAILED; } - //创建elementinfo - ArkUI_AccessibilityElementInfo* focusedElementInfo = - OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); - if (focusedElementInfo == nullptr) { + //flutterNodes converts to elementInfos + flutterSemanticsNodesToElementInfos(); + + //从elementinfolist中获取elementinfo + ArkUI_AccessibilityElementInfo* elementInfoFromList = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + if (elementInfoFromList == nullptr) { FML_DLOG(INFO) << "OhosAccessibilityBridge::FindAccessibilityNodeInfosById " - "elementInfo is null"; + "elementInfoFromList is null"; return OH_ARKUI_ACCESSIBILITY_RESULT_FAILED; } /** Search for current nodes. */ if(mode == ArkUI_AccessibilitySearchMode::NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { - flutterInitElementInfo(focusedElementInfo); + Flutter_InitSpercificElementInfoById(elementInfoFromList, elementId); } else if(ArkUI_AccessibilitySearchMode::NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS) { /** Search for parent nodes. */ - flutterInitElementInfo(focusedElementInfo); + Flutter_InitSpercificElementInfoById(elementInfoFromList, elementId); } else if(ArkUI_AccessibilitySearchMode::NATIVE_SEARCH_MODE_PREFETCH_SIBLINGS) { /** Search for sibling nodes. */ - flutterInitElementInfo(focusedElementInfo); + Flutter_InitSpercificElementInfoById(elementInfoFromList, elementId); } else if(ArkUI_AccessibilitySearchMode::NATIVE_SEARCH_MODE_PREFETCH_CHILDREN) { /** Search for child nodes at the next level. */ - flutterInitElementInfo(focusedElementInfo); + Flutter_InitSpercificElementInfoById(elementInfoFromList, elementId); } else { //ArkUI_AccessibilitySearchMode::NATIVE_SEARCH_MODE_PREFETCH_RECURSIVE_CHILDREN /** Search for all child nodes. */ - flutterInitElementInfo(focusedElementInfo); + Flutter_InitSpercificElementInfoById(elementInfoFromList, elementId); } + + //调用announce测试 + // auto char_arr = std::make_unique(6); + // for (int i = 0; i < 6; ++i) { + // char_arr[i] = '6'; + // } + // announce(char_arr); + FML_DLOG(INFO) << "OhosAccessibilityBridge::FindAccessibilityNodeInfosById is succeed!"; return OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS; } @@ -167,7 +277,10 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments *actionArguments, int32_t requestId) { - //todo ... + //todo 执行无障碍动作解析 + if(actionArguments == nullptr) { + + } return 0; } @@ -183,26 +296,29 @@ int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition(int64_t elem return 0; } -void OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent(ArkUI_AccessibilityProvider* provider) { - if(provider == nullptr) { - FML_DLOG(ERROR)<<"OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent provider = null"; - return; - } - //创建eventInfo对象 +/** + * 自定义无障碍异步事件发送 + */ +void OhosAccessibilityBridge::SendAccessibilityAsyncEvent(int64_t elementId, ArkUI_AccessibilityEventType eventType) { + //1.创建eventInfo对象 ArkUI_AccessibilityEventInfo *eventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); if(eventInfo == nullptr) { FML_DLOG(ERROR)<<"OH_ArkUI_CreateAccessibilityEventInfo eventInfo = null"; return; } - auto callback = [](int32_t errorCode) { - if(errorCode == 0) { - FML_DLOG(ERROR)<<"OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent errorCode = 0"; - } - }; + //2.将选中的elementinfo进行配置 + SEMANTICS_NODE_ currentFlutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); + + // auto callback = [](int32_t errorCode) { + // if(errorCode == 0) { + // FML_DLOG(ERROR)<<"OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent errorCode = 0"; + // } + // }; + //发送event到OH侧 - OH_ArkUI_SendAccessibilityAsyncEvent(provider, eventInfo, callback); + // OH_ArkUI_SendAccessibilityAsyncEvent(provider, eventInfo, callback); - FML_DLOG(ERROR)<<"OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent is succeed"; + FML_DLOG(ERROR)<<"OhosAccessibilityBridge::SendAccessibilityAsyncEvent is succeed"; return; } @@ -213,8 +329,7 @@ void OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent(ArkUI_Accessibil void OhosAccessibilityBridge::updateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { - FML_DLOG(INFO) - << ("Native C++ OhosAccessibilityBridge::updateSemantics is called"); + FML_DLOG(INFO)<< ("OhosAccessibilityBridge::updateSemantics is called"); std::set visitedObjs; // SEMANTICS_NODE_ rootObj = getRootSemanticsNode(); @@ -296,8 +411,7 @@ void OhosAccessibilityBridge::updateSemantics( // declare一个newChildren for (int32_t i = 0; i < newChildCount; i++) { // todo:通过遍历当前节点的子节点,并对所有子节点进行逐一构建os对应的elementinfo - // AccessibilityElementInfo child = - // createAccessibilityElementInfo(node.childrenInTraversalOrder[i]); + // AccessibilityElementInfo* child = createAccessibilityElementInfo(node.childrenInTraversalOrder[i]); // todo:将所有的新child节点加入到os对应的elementInfoList中 } // TODO: 将更新后的全部子节点赋值给当前真实节点 @@ -403,7 +517,7 @@ void OhosAccessibilityBridge::updateSemantics( // 获取根节点 flutter::SemanticsNode OhosAccessibilityBridge::getRootSemanticsNode() { if(!flutterSemanticsTree_.size()) { - FML_DLOG(ERROR)<<"OhosAccessibilityBridge::flutterInitElementInfo -> flutterSemanticsTree_.size()=0"; + FML_DLOG(ERROR)<<"OhosAccessibilityBridge::flutterSemanticsNodesToElementInfos -> flutterSemanticsTree_.size()=0"; return flutter::SemanticsNode{}; } return flutterSemanticsTree_.at(0); @@ -437,6 +551,10 @@ void OhosAccessibilityBridge::printTest(flutter::SemanticsNode node) { FML_DLOG(INFO) << "node.id=" << node.id; FML_DLOG(INFO) << "node.flags=" << node.flags; FML_DLOG(INFO) << "node.actions=" << node.actions; + FML_DLOG(INFO) << "node.rect.left=" << node.rect.fLeft; + FML_DLOG(INFO) << "node.rect.top=" << node.rect.fTop; + FML_DLOG(INFO) << "node.rect.right=" << node.rect.fRight; + FML_DLOG(INFO) << "node.rect.bottom=" << node.rect.fBottom; FML_DLOG(INFO) << "node.maxValueLength=" << node.maxValueLength; FML_DLOG(INFO) << "node.currentValueLength=" << node.currentValueLength; FML_DLOG(INFO) << "node.textSelectionBase=" << node.textSelectionBase; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 4206f4143c..777db8e6ac 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -49,7 +49,7 @@ class OhosAccessibilityBridge { flutter::CustomAccessibilityActionUpdates actions); // obtain the flutter semnatics node - flutter::SemanticsNode getOrCreateSemanticsNode(int32_t id); + flutter::SemanticsNode getOrCreateFlutterSemanticsNode(int32_t id); int32_t FindAccessibilityNodeInfosById(int64_t elementId, ArkUI_AccessibilitySearchMode mode, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList); int32_t FindAccessibilityNodeInfosByText(int64_t elementId, const char* text, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList); @@ -58,10 +58,14 @@ class OhosAccessibilityBridge { int32_t ExecuteAccessibilityAction(int64_t elementId, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments *actionArguments, int32_t requestId); int32_t ClearFocusedFocusAccessibilityNode(); int32_t GetAccessibilityNodeCursorPosition(int64_t elementId, int32_t requestId, int32_t* index); - void ArkUI_SendAccessibilityAsyncEvent(ArkUI_AccessibilityProvider* provider); + + void SendAccessibilityAsyncEvent(int64_t elementId, ArkUI_AccessibilityEventType eventType); + void Flutter_InitSpercificElementInfoById(ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId); + int32_t GetParentId(int64_t elementId); private: std::shared_ptr ax_manager_; + std::unordered_map parentChildIdMap; std::unordered_map flutterSemanticsTree_; std::vector flutterSemanticsTreeVec; std::unordered_map actions_mp_; @@ -73,7 +77,7 @@ class OhosAccessibilityBridge { // can be made during Flutter's navigation changes. std::vector flutterNavigationStack; - void flutterInitElementInfo(ArkUI_AccessibilityElementInfo* elementInfo); + void flutterSemanticsNodesToElementInfos(); flutter::SemanticsNode getRootSemanticsNode(); -- Gitee From b316a3e191b56ae5a2229ef518e377d2dbba16e5 Mon Sep 17 00:00:00 2001 From: zjxi Date: Sat, 7 Sep 2024 17:56:01 +0800 Subject: [PATCH 019/151] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9=E6=97=A0?= =?UTF-8?q?=E9=9A=9C=E7=A2=8Dbridge=E7=9A=84=E5=8D=95=E4=BE=8B=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E8=8E=B7=E5=8F=96instance=E7=9A=84bug=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E5=AE=8C=E5=96=84flutter=E8=AF=AD=E4=B9=89=E6=A0=91?= =?UTF-8?q?=E5=88=B0arkui=E8=AF=AD=E4=B9=89=E6=A0=91=E7=9A=84=E8=BD=AC?= =?UTF-8?q?=E5=8C=96=E4=BB=A3=E7=A0=81=EF=BC=8C=E8=8E=B7=E5=8F=96=E5=88=B0?= =?UTF-8?q?root=E8=8A=82=E7=82=B9=E5=B9=B6=E8=A7=A6=E5=8F=91ExecuteAccessi?= =?UTF-8?q?bilityAction=E6=8E=A5=E5=8F=A3=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 291 +++++++++++++----- .../accessibility/ohos_accessibility_bridge.h | 22 +- .../ohos/napi/platform_view_ohos_napi.cpp | 9 +- .../ohos/napi/platform_view_ohos_napi.h | 2 +- .../platform/ohos/ohos_xcomponent_adapter.cpp | 31 +- shell/platform/ohos/platform_view_ohos.cpp | 6 +- shell/platform/ohos/platform_view_ohos.h | 1 - 7 files changed, 255 insertions(+), 107 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index bb8a6d8f6c..f4cf828dcf 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -19,14 +19,16 @@ namespace flutter { -OhosAccessibilityBridge::OhosAccessibilityBridge() = default; -OhosAccessibilityBridge::~OhosAccessibilityBridge() = default; +OhosAccessibilityBridge OhosAccessibilityBridge::bridgeInstance; -OhosAccessibilityBridge& OhosAccessibilityBridge::GetInstance() { - static OhosAccessibilityBridge ohosAccessibilityBridge; - return ohosAccessibilityBridge; +OhosAccessibilityBridge::OhosAccessibilityBridge() {}; +OhosAccessibilityBridge::~OhosAccessibilityBridge() {}; + +OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() { + return &OhosAccessibilityBridge::bridgeInstance; } + void OhosAccessibilityBridge::announce(std::unique_ptr& message) { //创建并设置屏幕朗读事件 ArkUI_AccessibilityEventInfo* announceEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); @@ -52,28 +54,29 @@ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode( int32_t id) { flutter::SemanticsNode node; if (flutterSemanticsTree_.count(id) > 0) { - node = flutterSemanticsTree_.at(id); + return flutterSemanticsTree_.at(id); + FML_DLOG(INFO)<<"OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode get node.id="<(flutterNode.childrenInTraversalOrder.size()); + int64_t childNodeIds[childCount]; for(int32_t i=0; i(flutterNode.childrenInTraversalOrder[i]); + FML_DLOG(INFO) << "flutterSemanticsNodesToElementInfos flutterNode.id= "<(flutterNode.rect.fLeft); + int32_t top = static_cast(flutterNode.rect.fTop); + int32_t right = static_cast(flutterNode.rect.fRight); + int32_t bottom = static_cast(flutterNode.rect.fBottom); + ArkUI_AccessibleRect rect = {left, top, right, bottom}; + OH_ArkUI_SetAccessibilityElementInfoScreenRect(elementInfo, &rect); + + //设置elementinfo的action类型 + int32_t actionTypeNum = 3; + ArkUI_AccessibleAction actions[actionTypeNum]; + actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS; + actions[0].description = "flutter-ohos"; + actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].description = "flutter-ohos"; + actions[2].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_LONG_CLICK; + actions[2].description = "flutter-ohos"; + OH_ArkUI_SetAccessibilityElementInfoOperationActions(elementInfo, actionTypeNum, actions); + + //设置无障碍相关属性 + OH_ArkUI_SetAccessibilityElementInfoAccessibilityText(elementInfo, flutterNode.label.c_str()); + OH_ArkUI_SetAccessibilityElementInfoAccessibilityLevel(elementInfo, "yes"); + OH_ArkUI_SetAccessibilityElementInfoAccessibilityGroup(elementInfo, false); } + FML_DLOG(ERROR)<<"flutterSemanticsNodesToElementInfos is end"; } /** @@ -130,19 +177,77 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi "elementInfoFromList is null"; return; } + FML_DLOG(INFO) << "Flutter_InitSpercificElementInfoById elementInfoFromList= "<(0)); + //根据flutternode信息配置对应的elementinfo + OH_ArkUI_SetAccessibilityElementInfoElementId(elementInfoFromList, 0); + //设置父节点id + OH_ArkUI_SetAccessibilityElementInfoParentId(elementInfoFromList, -999); + //设置无障碍播报文本 + OH_ArkUI_SetAccessibilityElementInfoAccessibilityText(elementInfoFromList, "-1"); + OH_ArkUI_SetAccessibilityElementInfoAccessibilityLevel(elementInfoFromList, "yes"); + OH_ArkUI_SetAccessibilityElementInfoAccessibilityGroup(elementInfoFromList, false); + + //配置child节点信息 + int32_t childCount = static_cast(flutterNode.childrenInTraversalOrder.size()); + int64_t childNodeIds[childCount]; + for(int32_t i=0; i(flutterNode.childrenInTraversalOrder[i]); + FML_DLOG(INFO) << "Flutter_InitSpercificElementInfoById elementid= "<(flutterNode.rect.fLeft); + int32_t top = static_cast(flutterNode.rect.fTop); + int32_t right = static_cast(flutterNode.rect.fRight); + int32_t bottom = static_cast(flutterNode.rect.fBottom); + ArkUI_AccessibleRect rect = {left, top, right, bottom}; + OH_ArkUI_SetAccessibilityElementInfoScreenRect(elementInfoFromList, &rect); + + + //设置elementinfo的action类型 + int32_t actionTypeNum = 2; + ArkUI_AccessibleAction actions[actionTypeNum]; + actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS; + actions[0].description = "flutter-ohos"; + actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].description = "flutter-ohos"; + OH_ArkUI_SetAccessibilityElementInfoOperationActions(elementInfoFromList, actionTypeNum, actions); + return; + } + //根据elementid获取对应的flutter节点 - SEMANTICS_NODE_ flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); + FML_DLOG(INFO) << "OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById elementId = "<(elementId)); //根据flutternode信息配置对应的elementinfo OH_ArkUI_SetAccessibilityElementInfoElementId(elementInfoFromList, flutterNode.id); + //设置父节点id int32_t parentId = GetParentId(elementId); if(parentId < 0) { + OH_ArkUI_SetAccessibilityElementInfoParentId(elementInfoFromList, parentId); FML_DLOG(INFO) << "OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById " "GetParentId is null"; return; + } else { + OH_ArkUI_SetAccessibilityElementInfoParentId(elementInfoFromList, parentId); + FML_DLOG(INFO) << "OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById GetParentId = "<(flutterNode.rect.fLeft); int32_t top = static_cast(flutterNode.rect.fTop); @@ -181,13 +298,17 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi OH_ArkUI_SetAccessibilityElementInfoAccessibilityGroup(elementInfoFromList, false); //设置elementinfo的action类型 - int32_t actionTypeNum = 2; + int32_t actionTypeNum = 3; ArkUI_AccessibleAction actions[actionTypeNum]; actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS; actions[0].description = "flutter-ohos"; - actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_CLICK; + actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS; actions[1].description = "flutter-ohos"; + actions[2].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_CLICK; + actions[2].description = "flutter-ohos"; OH_ArkUI_SetAccessibilityElementInfoOperationActions(elementInfoFromList, actionTypeNum, actions); + + FML_DLOG(INFO) << "OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById is end"; } /** @@ -200,47 +321,47 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( ArkUI_AccessibilitySearchMode mode, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { + + if(flutterSemanticsTree_.size() == 0) { + FML_DLOG(INFO) << "FindAccessibilityNodeInfosById flutterSemanticsTree_.size() = 0"; + return OH_ARKUI_ACCESSIBILITY_RESULT_FAILED; + } + if (elementList == nullptr) { - FML_DLOG(INFO) << "OhosAccessibilityBridge::FindAccessibilityNodeInfosById " - "elementList is null"; + FML_DLOG(INFO) << "FindAccessibilityNodeInfosById elementList is null"; return OH_ARKUI_ACCESSIBILITY_RESULT_FAILED; } - //flutterNodes converts to elementInfos - flutterSemanticsNodesToElementInfos(); //从elementinfolist中获取elementinfo ArkUI_AccessibilityElementInfo* elementInfoFromList = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + FML_DLOG(INFO) << "FindAccessibilityNodeInfosById elementId = "<(elementId)); - // auto callback = [](int32_t errorCode) { - // if(errorCode == 0) { - // FML_DLOG(ERROR)<<"OhosAccessibilityBridge::ArkUI_SendAccessibilityAsyncEvent errorCode = 0"; - // } - // }; + //2.创建的elementinfo并根据对应id的flutternode进行属性初始化 + ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); + Flutter_InitSpercificElementInfoById(_elementInfo, elementId); + + //3.设置发送事件,如配置获焦事件 + OH_ArkUI_SetAccessibilityEventEventType(eventInfo, eventType); + + //4.将eventinfo事件和当前elementinfo进行绑定 + OH_ArkUI_SetAccessibilityEventElementInfo(eventInfo, _elementInfo); - //发送event到OH侧 - // OH_ArkUI_SendAccessibilityAsyncEvent(provider, eventInfo, callback); + //5.调用接口发送到ohos侧 + auto callback = [](int32_t errorCode) { + FML_DLOG(ERROR)<<"OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent callback-> errorCode ="< flutterSemanticsTree_.size()=0"; return flutter::SemanticsNode{}; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 777db8e6ac..58ff732d56 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -38,10 +38,12 @@ typedef flutter::SemanticsNode SEMANTICS_NODE_; */ class OhosAccessibilityBridge { public: - OhosAccessibilityBridge(); + OhosAccessibilityBridge(); ~OhosAccessibilityBridge(); + + static OhosAccessibilityBridge* GetInstance(); + bool isOhosAccessibilityEnabled_; - static OhosAccessibilityBridge& GetInstance(); void announce(std::unique_ptr& message); @@ -58,32 +60,28 @@ class OhosAccessibilityBridge { int32_t ExecuteAccessibilityAction(int64_t elementId, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments *actionArguments, int32_t requestId); int32_t ClearFocusedFocusAccessibilityNode(); int32_t GetAccessibilityNodeCursorPosition(int64_t elementId, int32_t requestId, int32_t* index); + ArkUI_AccessibilityProvider* provider_; - void SendAccessibilityAsyncEvent(int64_t elementId, ArkUI_AccessibilityEventType eventType); + void Flutter_SendAccessibilityAsyncEvent(int64_t elementId, ArkUI_AccessibilityEventType eventType); void Flutter_InitSpercificElementInfoById(ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId); int32_t GetParentId(int64_t elementId); private: + static OhosAccessibilityBridge bridgeInstance; std::shared_ptr ax_manager_; std::unordered_map parentChildIdMap; std::unordered_map flutterSemanticsTree_; - std::vector flutterSemanticsTreeVec; std::unordered_map actions_mp_; static const int32_t ROOT_NODE_ID = 0; - // int32_t previousRouteId = ROOT_NODE_ID; + + void flutterSemanticsNodesToElementInfos(ArkUI_AccessibilityElementInfoList* elementInfoList); + flutter::SemanticsNode getFlutterRootSemanticsNode(); // A Java/Android cached representation of the Flutter app's navigation stack. // The Flutter navigation stack is tracked so that accessibility announcements // can be made during Flutter's navigation changes. std::vector flutterNavigationStack; - void flutterSemanticsNodesToElementInfos(); - - flutter::SemanticsNode getRootSemanticsNode(); - - - // native os interfaces - /** * Informs the TalkBack user about window name changes. * it creates a {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED} and sends diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index 74dac221e9..abc8a4c8e1 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -32,7 +32,6 @@ #include "flutter/shell/platform/ohos/surface/ohos_native_window.h" #include "flutter/shell/platform/ohos/types.h" #include "unicode/uchar.h" -#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" #define OHOS_SHELL_HOLDER (reinterpret_cast(shell_holder)) namespace flutter { @@ -1848,8 +1847,8 @@ napi_value PlatformViewOHOSNapi::nativeAccessibilityStateChange( "%{public}s", (state ? "true" : "false")); // 传递到无障碍管理类 - OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); - ohosAccessibilityBridge.isOhosAccessibilityEnabled_ = state; + auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge->isOhosAccessibilityEnabled_ = state; return nullptr; } @@ -1868,8 +1867,8 @@ napi_value PlatformViewOHOSNapi::nativeAnnounce( napi_get_value_string_utf8(env, args[0], char_array.get(), null_terminated_length, nullptr); LOGD("PlatformViewOHOSNapi::nativeAnnounce message: %{public}s", char_array.get()); - OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); - ohosAccessibilityBridge.announce(char_array); + auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge->announce(char_array); return nullptr; } diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h index 844b140bdf..64af83931b 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.h +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -28,7 +28,7 @@ #include "flutter/shell/common/run_configuration.h" #include "flutter/shell/platform/ohos/napi_common.h" #include "napi/native_api.h" -#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_manager.h" +#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" // class for all c++ to call js function namespace flutter { diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp index c1d1eed184..c8df5699f5 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.cpp +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -276,8 +276,8 @@ int32_t FindAccessibilityNodeInfosById( int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { - OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); - ohosAccessibilityBridge.FindAccessibilityNodeInfosById(elementId, mode, requestId, elementList); + auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge->FindAccessibilityNodeInfosById(elementId, mode, requestId, elementList); LOGD("accessibilityProviderCallback_.FindAccessibilityNodeInfosById"); return 0; } @@ -289,8 +289,8 @@ int32_t FindAccessibilityNodeInfosByText( int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { - OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); - ohosAccessibilityBridge.FindAccessibilityNodeInfosByText(elementId, text, requestId, elementList); + auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge->FindAccessibilityNodeInfosByText(elementId, text, requestId, elementList); LOGD("accessibilityProviderCallback_.FindAccessibilityNodeInfosByText"); return 0; } @@ -300,8 +300,8 @@ int32_t FindFocusedAccessibilityNode( int64_t elementId, ArkUI_AccessibilityFocusType focusType, int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo) { - OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); - ohosAccessibilityBridge.FindFocusedAccessibilityNode(elementId, focusType, requestId, elementinfo); + auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge->FindFocusedAccessibilityNode(elementId, focusType, requestId, elementinfo); LOGD("accessibilityProviderCallback_.FindFocusedAccessibilityNode"); return 0; } @@ -313,8 +313,8 @@ int32_t FindNextFocusAccessibilityNode( int32_t requestId, ArkUI_AccessibilityElementInfo *elementList) { - OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); - ohosAccessibilityBridge.FindNextFocusAccessibilityNode(elementId, direction, requestId, elementList); + auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge->FindNextFocusAccessibilityNode(elementId, direction, requestId, elementList); LOGD("accessibilityProviderCallback_.FindNextFocusAccessibilityNode"); return 0; } @@ -326,8 +326,8 @@ int32_t ExecuteAccessibilityAction( ArkUI_AccessibilityActionArguments* actionArguments, int32_t requestId) { - OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); - ohosAccessibilityBridge.ExecuteAccessibilityAction(elementId, action, actionArguments, requestId); + auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge->ExecuteAccessibilityAction(elementId, action, actionArguments, requestId); LOGD("accessibilityProviderCallback_.ExecuteAccessibilityAction"); return 0; } @@ -345,8 +345,8 @@ int32_t GetAccessibilityNodeCursorPosition( int32_t requestId, int32_t* index) { - OhosAccessibilityBridge ohosAccessibilityBridge = flutter::OhosAccessibilityBridge::GetInstance(); - ohosAccessibilityBridge.GetAccessibilityNodeCursorPosition(elementId, requestId, index); + auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge->GetAccessibilityNodeCursorPosition(elementId, requestId, index); LOGD("accessibilityProviderCallback_.GetAccessibilityNodeCursorPosition"); return 0; } @@ -416,9 +416,12 @@ void XComponentBase::SetNativeXComponent(OH_NativeXComponent* nativeXComponent){ return; } LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is %{public}d", ret2); - // ohosAccessibilityBridge.ArkUI_SendAccessibilityAsyncEvent(accessibilityProvider); + + //将ArkUI_AccessibilityProvider传到无障碍bridge类 + auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge->provider_ = accessibilityProvider; + LOGI("XComponentBase::SetNativeXComponent OH_ArkUI_AccessibilityProviderRegisterCallback is succeed"); - } } diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index 6b588641aa..a61d021b49 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -109,9 +109,6 @@ PlatformViewOHOS::PlatformViewOHOS( LOGI("ohos_surface_ end 2"); ohos_surface_ = surface_factory_->CreateSurface(); LOGI("ohos_surface_ end 3"); - - ax_bridge_delegate_ = OhosAccessibilityBridge::GetInstance(); - FML_CHECK(ohos_surface_ && ohos_surface_->IsValid()) << "Could not create an OpenGL, Vulkan or Software surface to set " "up " @@ -300,7 +297,8 @@ void PlatformViewOHOS::UpdateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { FML_DLOG(INFO) << "PlatformViewOHOS::UpdateSemantics is called"; - ax_bridge_delegate_.updateSemantics(update, actions); + auto ax_bridge_delegate_ = OhosAccessibilityBridge::GetInstance(); + ax_bridge_delegate_->updateSemantics(update, actions); } // |PlatformView| diff --git a/shell/platform/ohos/platform_view_ohos.h b/shell/platform/ohos/platform_view_ohos.h index 3fc4d815d1..c712405e51 100644 --- a/shell/platform/ohos/platform_view_ohos.h +++ b/shell/platform/ohos/platform_view_ohos.h @@ -142,7 +142,6 @@ class PlatformViewOHOS final : public PlatformView { std::map contextDatas_; std::shared_ptr platform_view_ohos_delegate_; - OhosAccessibilityBridge ax_bridge_delegate_; static bool isDestroyed_; static pthread_mutex_t mutex_; -- Gitee From d19b20fe54615feecbbd6e8a5509a9f89baeef65 Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 9 Sep 2024 11:32:24 +0800 Subject: [PATCH 020/151] =?UTF-8?q?feat:=E5=AE=9E=E7=8E=B0root=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E7=9A=84=E6=96=87=E5=AD=97=E6=9C=97=E8=AF=BB,=20FindA?= =?UTF-8?q?ccessibilityNodeInfosById=E5=92=8CExecuteAccessibilityAction?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=AD=A3=E5=B8=B8=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- lib/ui/window/platform_configuration.cc | 4 +- runtime/runtime_controller.cc | 2 +- shell/common/engine.cc | 2 +- shell/common/shell.cc | 2 +- .../ohos_accessibility_bridge.cpp | 66 +++++++++---------- .../accessibility/ohos_accessibility_bridge.h | 2 +- .../src/main/ets/view/AccessibilityBridge.ets | 10 --- shell/platform/ohos/platform_view_ohos.cpp | 4 +- 8 files changed, 39 insertions(+), 53 deletions(-) diff --git a/lib/ui/window/platform_configuration.cc b/lib/ui/window/platform_configuration.cc index cdd348a5dd..1f20776fba 100644 --- a/lib/ui/window/platform_configuration.cc +++ b/lib/ui/window/platform_configuration.cc @@ -185,7 +185,7 @@ void PlatformConfiguration::DispatchSemanticsAction(int32_t id, fml::MallocMapping args) { std::shared_ptr dart_state = dispatch_semantics_action_.dart_state().lock(); - FML_DLOG(INFO) << "PlatformConfiguration::DispatchSemanticsAction : " << id; + if (!dart_state) { return; } @@ -197,7 +197,7 @@ void PlatformConfiguration::DispatchSemanticsAction(int32_t id, if (Dart_IsError(args_handle)) { return; } - + FML_DLOG(INFO) << "PlatformConfiguration::DispatchSemanticsAction: id=" << id<<" action="<(action); tonic::CheckAndHandleError(tonic::DartInvoke( dispatch_semantics_action_.Get(), {tonic::ToDart(id), tonic::ToDart(static_cast(action)), diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index 540ad7452b..f39452f9ea 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -288,7 +288,7 @@ bool RuntimeController::DispatchSemanticsAction(int32_t id, if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) { platform_configuration->DispatchSemanticsAction(id, action, std::move(args)); - FML_DLOG(INFO) << "RuntimeController::DispatchSemanticsAction, id="<(flutterNode.childrenInTraversalOrder[i]); - FML_DLOG(INFO) << "flutterSemanticsNodesToElementInfos flutterNode.id= "< errorCode ="< errorCode ="< flutterSemanticsTree_.size()=0"; + FML_DLOG(ERROR)<<"OhosAccessibilityBridge::FlutterTreeToArkuiTree -> flutterSemanticsTree_.size()=0"; return flutter::SemanticsNode{}; } return flutterSemanticsTree_.at(0); } void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { - + //todo ... } void OhosAccessibilityBridge::removeSemanticsNode( flutter::SemanticsNode nodeToBeRemoved) { + //todo ... if(!flutterSemanticsTree_.size()) { FML_DLOG(ERROR)<<"OhosAccessibilityBridge::removeSemanticsNode -> flutterSemanticsTree_.szie()=0"; return; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 58ff732d56..40b4b40327 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -74,7 +74,7 @@ class OhosAccessibilityBridge { std::unordered_map actions_mp_; static const int32_t ROOT_NODE_ID = 0; - void flutterSemanticsNodesToElementInfos(ArkUI_AccessibilityElementInfoList* elementInfoList); + void FlutterTreeToArkuiTree(ArkUI_AccessibilityElementInfoList* elementInfoList); flutter::SemanticsNode getFlutterRootSemanticsNode(); // A Java/Android cached representation of the Flutter app's navigation stack. diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets index 1cfc8a801a..1ce465a8a4 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets @@ -43,18 +43,8 @@ export default class AccessibilityBridge implements AccessibilityMessageHandler onTooltip(nodeId: string): void { throw new Error('Method not implemented.'); - // android -> AccessibilityEvent e = - // obtainAccessibilityEvent(ROOT_NODE_ID, AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); - // e.getText().add(message); - // sendAccessibilityEvent(e); } - /** - * updateSemantics、updateCustomAccessibilityActions的debug流程,该过程只在native c++层实现,后续会删除 - * @param buffer - * @param strings - * @param stringAttributeArgs - */ updateSemantics(buffer: ByteBuffer, strings: string[], stringAttributeArgs: ByteBuffer[]): void { Log.d(TAG, "AccessibilityBridge.ets updateSemantics is called"); } diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index a61d021b49..e419f7935e 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -224,7 +224,7 @@ void PlatformViewOHOS::DispatchPlatformMessage(std::string name, void* message, int messageLenth, int reponseId) { - FML_DLOG(INFO) << "DispatchSemanticsAction(" << name << ",," << messageLenth + FML_DLOG(INFO) << "DispatchPlatformMessage(" << name << "," << messageLenth << "," << reponseId; fml::MallocMapping mapMessage = fml::MallocMapping::Copy(message, messageLenth); @@ -255,7 +255,7 @@ void PlatformViewOHOS::DispatchSemanticsAction(int id, int action, void* actionData, int actionDataLenth) { - FML_DLOG(INFO) << "DispatchSemanticsAction(" << id << "," << action << "," + FML_DLOG(INFO) << "DispatchSemanticsAction(id=" << id << ", action=" << action << ", actionDataLenth" << actionDataLenth; auto args_vector = fml::MallocMapping::Copy(actionData, actionDataLenth); -- Gitee From 202b5d416ccd4901e86dc7f9dc6420d07b58a7e5 Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 9 Sep 2024 16:29:40 +0800 Subject: [PATCH 021/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0nativeSetSemanti?= =?UTF-8?q?csEnabled=E6=8E=A5=E5=8F=A3,=E5=B0=86=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8D=E7=B3=BB=E7=BB=9F=E7=9B=91=E5=90=AC=E7=BB=93=E6=9E=9C?= =?UTF-8?q?=E6=A1=A5=E6=8E=A5=E5=88=B0shellholder=E4=B8=8A,=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0updatesemantics=E6=96=B9=E6=B3=95=E7=9A=84=E5=8F=AF?= =?UTF-8?q?=E6=8E=A7=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- runtime/platform_data.h | 2 +- .../ohos_accessibility_bridge.cpp | 35 ++++++++++++++--- .../src/main/cpp/types/libflutter/index.d.ets | 6 ++- .../main/ets/embedding/engine/FlutterNapi.ets | 39 +++++++------------ .../engine/renderer/FlutterRenderer.ets | 1 + .../systemchannels/AccessibilityChannel.ets | 2 +- .../ets/embedding/ohos/FlutterAbility.ets | 1 + .../flutter/src/main/ets/view/FlutterView.ets | 3 +- shell/platform/ohos/library_loader.cpp | 4 +- .../ohos/napi/platform_view_ohos_napi.cpp | 35 +++++++++++++++++ .../ohos/napi/platform_view_ohos_napi.h | 4 ++ 11 files changed, 94 insertions(+), 38 deletions(-) diff --git a/runtime/platform_data.h b/runtime/platform_data.h index 92dfdf5da7..ca7b683a1e 100644 --- a/runtime/platform_data.h +++ b/runtime/platform_data.h @@ -38,7 +38,7 @@ struct PlatformData { std::vector locale_data; std::string user_settings_data = "{}"; std::string lifecycle_state; - bool semantics_enabled = true; //debug + bool semantics_enabled = false; bool assistive_technology_enabled = false; int32_t accessibility_feature_flags_ = 0; }; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index d94ce80cdf..4b70cd157d 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -314,13 +314,14 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi /** * Called to obtain element information based on a specified node. * NOTE: 该arkui接口需要在系统无障碍服务开启时,才能触发调用 - * TODO: 当前实现版本为实现简易功能,仅对flutter语义focused节点进行交互,后续完善并优化 + * TODO: 当前实现版本为实现简易功能,正在完善实现实际使用场景逻辑并逐步优化;另外:ohos侧当前只发送elementinfo=-1、0两种情况,故目前只能获取root节点 */ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( int64_t elementId, ArkUI_AccessibilitySearchMode mode, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { + FML_DLOG(INFO) << "FindAccessibilityNodeInfosById params: elementId = "< errorCode ="< errorCode ="< string; */ export const nativeSetAccessibilityFeatures: (accessibilityFeatureFlags: number, responseId: number) => void; -export const nativeAccessibilityStateChange: (state: Boolean) => string; +export const nativeAccessibilityStateChange: (state: Boolean) => void; -export const nativeAnnounce: (message: string) => string; +export const nativeAnnounce: (message: string) => void; + +export const nativeSetSemanticsEnabled: (nativeShellHolderId: number, enabled: boolean) => void; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index 29a2fcd479..b2ec0b7df0 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -315,9 +315,10 @@ export default class FlutterNapi { } } - setSemanticsEnabled(enabled: boolean, responseId: number): void { + setSemanticsEnabled2(enabled: boolean, responseId: number): void { + this.ensureRunningOnMainThread(); if (this.isAttached()) { - this.nativeSetSemanticsEnabled(enabled); + flutter.nativeSetSemanticsEnabled(this.nativeShellHolderId!, enabled); } else { Log.w( TAG, @@ -326,8 +327,16 @@ export default class FlutterNapi { } } - // Send an empty response to a platform message received from Dart. - nativeSetSemanticsEnabled(enabled: boolean):void {} + setSemanticsEnabled(enabled: boolean): void { + this.ensureRunningOnMainThread(); + if (this.isAttached()) { + flutter.nativeSetSemanticsEnabled(this.nativeShellHolderId!, enabled); + } else { + Log.e( + TAG, + "Tried to send a platform message response, but FlutterNapi was detached from native C++. Could not send."); + } + } setAccessibilityFeatures(accessibilityFeatureFlags: number, responseId: number): void { if (this.isAttached()) { @@ -367,28 +376,6 @@ export default class FlutterNapi { } } - - // debug updateSemantics - updateSemantics(buffer: ByteBuffer, strings: string[], stringAttributeArgs: ByteBuffer[]): void { - this.ensureRunningOnMainThread(); - if(this.accessibilityDelegate != null) { - this.accessibilityDelegate.updateSemantics(buffer, strings, stringAttributeArgs); - } - // TODO(mattcarroll): log dropped messages when in debug mode - // (https://github.com/flutter/flutter/issues/25391) - Log.d(TAG, "updateSemantics is called"); - flutter.nativeUpdateSemantics(buffer, strings, stringAttributeArgs); - } - - updateCustomAccessibilityActions(buffer: ByteBuffer, strings: string[]): void { - this.ensureRunningOnMainThread(); - if(this.accessibilityDelegate != null) { - this.accessibilityDelegate.updateCustomAccessibilityActions(buffer, strings); - } - Log.d(TAG, "updateCustomAccessibilityActions is called"); - flutter.nativeUpdateCustomAccessibilityActions(buffer, strings); - } - accessibilityStateChange(state: Boolean): void { this.ensureRunningOnMainThread(); if(this.accessibilityDelegate != null) { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/renderer/FlutterRenderer.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/renderer/FlutterRenderer.ets index 5d9fe37697..2215411814 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/renderer/FlutterRenderer.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/renderer/FlutterRenderer.ets @@ -101,6 +101,7 @@ export class FlutterRenderer implements TextureRegistry { }) }) } + } export class SurfaceTextureRegistryEntry implements SurfaceTextureEntry { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets index bb733649cc..6a9aa7d3a9 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets @@ -94,7 +94,7 @@ export default class AccessibilityChannel implements MessageHandler{ onOhosAccessibilityEnabled(): void { let replyId: number = this.nextReplyId++; - this.flutterNapi.setSemanticsEnabled(true, replyId); + this.flutterNapi.setSemanticsEnabled2(true, replyId); Log.i(AccessibilityChannel.TAG, "onOhosAccessibilityEnabled = true"); } diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets index 22c1563ba8..9e589b21c1 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets @@ -36,6 +36,7 @@ import appRecovery from '@ohos.app.ability.appRecovery'; import FlutterManager from './FlutterManager'; import { FlutterView } from '../../view/FlutterView'; import ApplicationInfoLoader from '../engine/loader/ApplicationInfoLoader'; +import { accessibility } from '@kit.AccessibilityKit'; const TAG = "FlutterAbility"; const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS'; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index 75e449666f..75b1aee544 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -108,9 +108,10 @@ export class FlutterView { this.mainWindow?.on('avoidAreaChange', this.avoidAreaChangeCallback); this.mainWindow?.on('windowStatusChange', this.windowStatusChangeCallback); + //监听系统是否开启无障碍服务 accessibility.on('accessibilityStateChange', (data: boolean) => { Log.i(TAG, `subscribe accessibility state change, result: ${JSON.stringify(data)}`); - this.flutterEngine?.getFlutterNapi()?.accessibilityStateChange(data); + this.flutterEngine?.getFlutterNapi()?.setSemanticsEnabled(data); }); } diff --git a/shell/platform/ohos/library_loader.cpp b/shell/platform/ohos/library_loader.cpp index e70264a03f..3c0ab4ff88 100644 --- a/shell/platform/ohos/library_loader.cpp +++ b/shell/platform/ohos/library_loader.cpp @@ -145,7 +145,9 @@ static napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_FUNCTION( "nativeAnnounce", flutter::PlatformViewOHOSNapi::nativeAnnounce), - + DECLARE_NAPI_FUNCTION( + "nativeSetSemanticsEnabled", + flutter::PlatformViewOHOSNapi::nativeSetSemanticsEnabled), }; FML_DLOG(INFO) << "Init NAPI size=" << sizeof(desc) / sizeof(desc[0]); diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index abc8a4c8e1..0729057c2a 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1849,6 +1849,7 @@ napi_value PlatformViewOHOSNapi::nativeAccessibilityStateChange( // 传递到无障碍管理类 auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge->isOhosAccessibilityEnabled_ = state; + return nullptr; } @@ -1872,4 +1873,38 @@ napi_value PlatformViewOHOSNapi::nativeAnnounce( return nullptr; } +napi_value PlatformViewOHOSNapi::nativeSetSemanticsEnabled(napi_env env, napi_callback_info info) { + napi_status ret; + size_t argc = 2; + napi_value args[2] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeSetSemanticsEnabled " + "napi_get_cb_info error:" + << ret; + return nullptr; + } + + int64_t shell_holder; + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeSetSemanticsEnabled " + "napi_get_value_bool error:" + << ret; + return nullptr; + } + bool enabled = false; + ret = napi_get_value_bool(env, args[1], &enabled); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeSetSemanticsEnabled " + "napi_get_value_bool error:" + << ret; + return nullptr; + } + OHOS_SHELL_HOLDER->GetPlatformView()->SetSemanticsEnabled(enabled); + FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeSetSemanticsEnabled " + "OHOS_SHELL_HOLDER->GetPlatformView()->SetSemanticsEnabled= "< Date: Mon, 9 Sep 2024 22:12:59 +0800 Subject: [PATCH 022/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0isNodeFocusable?= =?UTF-8?q?=E5=92=8CgetNodeComponentType=E5=8A=9F=E8=83=BD=E5=87=BD?= =?UTF-8?q?=E6=95=B0,=E5=AE=8C=E5=96=84=E8=8A=82=E7=82=B9=E8=8E=B7?= =?UTF-8?q?=E7=84=A6=E5=92=8C=E7=BB=84=E4=BB=B6=E7=B1=BB=E5=9E=8B=E5=88=A4?= =?UTF-8?q?=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 166 +++++++++++++----- .../accessibility/ohos_accessibility_bridge.h | 25 +-- .../ohos/napi/platform_view_ohos_napi.cpp | 3 +- .../ohos/napi/platform_view_ohos_napi.h | 1 - 4 files changed, 135 insertions(+), 60 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 4b70cd157d..4cda3ddff0 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -16,6 +16,7 @@ #include #include "flutter/fml/logging.h" #include "ohos_accessibility_bridge.h" +#include "flutter/shell/platform/ohos/ohos_shell_holder.h" namespace flutter { @@ -55,10 +56,9 @@ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode( flutter::SemanticsNode node; if (flutterSemanticsTree_.count(id) > 0) { return flutterSemanticsTree_.at(id); - FML_DLOG(INFO)<<"OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode get node.id="<(flutterNode.childrenInTraversalOrder[i]); FML_DLOG(INFO) << "FlutterTreeToArkuiTree flutterNode.id= "<(flutterNode.childrenInTraversalOrder[i]); - FML_DLOG(INFO) << "Flutter_InitSpercificElementInfoById elementid= "< elementid= "<<0<<" childCount= "<(flutterNode.childrenInTraversalOrder.size()); @@ -260,6 +262,7 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi OH_ArkUI_SetAccessibilityElementInfoChildNodeIds(elementInfoFromList, childCount, childNodeIds); // 配置常用属性,force to true for debugging + OH_ArkUI_SetAccessibilityElementInfoClickable(elementInfoFromList, true); OH_ArkUI_SetAccessibilityElementInfoCheckable(elementInfoFromList, true); OH_ArkUI_SetAccessibilityElementInfoFocusable(elementInfoFromList, true); if(elementId == 4) { @@ -276,7 +279,7 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi } else if(elementId == 4) { OH_ArkUI_SetAccessibilityElementInfoComponentType(elementInfoFromList, "button"); } else { - OH_ArkUI_SetAccessibilityElementInfoComponentType(elementInfoFromList, "text"); + OH_ArkUI_SetAccessibilityElementInfoComponentType(elementInfoFromList, ""); } //设置elementinfo的屏幕坐标范围 @@ -321,7 +324,7 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( ArkUI_AccessibilitySearchMode mode, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { - FML_DLOG(INFO) << "FindAccessibilityNodeInfosById params: elementId = "<(flutterSemanticsTree_.size()); + // for(int64_t i=1; i(flutterSemanticsTree_.size()); + for(int64_t i=1; i flutterNode is focusable, node.id="<& message); void updateSemantics(flutter::SemanticsNodeUpdates update, @@ -68,34 +70,23 @@ class OhosAccessibilityBridge { private: static OhosAccessibilityBridge bridgeInstance; + std::shared_ptr ax_manager_; std::unordered_map parentChildIdMap; std::unordered_map flutterSemanticsTree_; std::unordered_map actions_mp_; + std::vector flutterNavigationStack; + static const int32_t ROOT_NODE_ID = 0; void FlutterTreeToArkuiTree(ArkUI_AccessibilityElementInfoList* elementInfoList); + flutter::SemanticsNode getFlutterRootSemanticsNode(); + bool IsNodeFocusable(const flutter::SemanticsNode& node); + std::string GetNodeComponentType(const flutter::SemanticsNode& node); - // A Java/Android cached representation of the Flutter app's navigation stack. - // The Flutter navigation stack is tracked so that accessibility announcements - // can be made during Flutter's navigation changes. - std::vector flutterNavigationStack; - /** - * Informs the TalkBack user about window name changes. - * it creates a {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED} and sends - * the event to Android's accessibility system. In both cases, TalkBack - * announces the label of the route and re-addjusts the accessibility focus. - * - *

The given {@code route} should be a {@link SemanticsNode} that - * represents a navigation route in the Flutter app. - */ void onWindowNameChange(flutter::SemanticsNode route); - /** - * Hook called just before a {@link SemanticsNode} is removed from the Android cache of Flutter's - * semantics tree. - */ void removeSemanticsNode(flutter::SemanticsNode nodeToBeRemoved); void printTest(flutter::SemanticsNode node); diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index 0729057c2a..5cf0548cf2 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -353,6 +353,7 @@ std::vector splitString(const std::string& input, char delimiter) { return result; } + flutter::locale PlatformViewOHOSNapi::resolveNativeLocale( std::vector supportedLocales) { if (supportedLocales.empty()) { @@ -1889,7 +1890,7 @@ napi_value PlatformViewOHOSNapi::nativeSetSemanticsEnabled(napi_env env, napi_ca ret = napi_get_value_int64(env, args[0], &shell_holder); if (ret != napi_ok) { FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeSetSemanticsEnabled " - "napi_get_value_bool error:" + "napi_get_value_int64 error:" << ret; return nullptr; } diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h index 7c0b081fbe..f6597f35ad 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.h +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -29,7 +29,6 @@ #include "flutter/shell/platform/ohos/napi_common.h" #include "napi/native_api.h" #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" -#include "flutter/runtime/platform_data.h" // class for all c++ to call js function namespace flutter { -- Gitee From b95e0ca03b641d635b979b240108f917b45293e2 Mon Sep 17 00:00:00 2001 From: zjxi Date: Tue, 10 Sep 2024 11:39:37 +0800 Subject: [PATCH 023/151] =?UTF-8?q?feat:=E6=B7=BB=E5=8A=A0=E6=97=A0?= =?UTF-8?q?=E9=9A=9C=E7=A2=8Dbridge=E7=B1=BB=E4=B8=AD=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 77 ++++++++++--------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 4cda3ddff0..5bdbc0a36c 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -116,13 +116,14 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree(ArkUI_AccessibilityElementI OH_ArkUI_SetAccessibilityElementInfoClickable(elementInfo, true); //设置组件类型 + std::string componentTypeName = GetNodeComponentType(flutterNode); if(flutterNode.id == 4) { - OH_ArkUI_SetAccessibilityElementInfoComponentType(elementInfo, "button"); + OH_ArkUI_SetAccessibilityElementInfoComponentType(elementInfo, componentTypeName.c_str()); OH_ArkUI_SetAccessibilityElementInfoFocused(elementInfo, true); } else { - OH_ArkUI_SetAccessibilityElementInfoComponentType(elementInfo, "text"); + OH_ArkUI_SetAccessibilityElementInfoComponentType(elementInfo, componentTypeName.c_str()); } - OH_ArkUI_SetAccessibilityElementInfoContents(elementInfo, "root_content"); + OH_ArkUI_SetAccessibilityElementInfoContents(elementInfo, componentTypeName.c_str()); //设置elementinfo的屏幕坐标范围 int32_t left = static_cast(flutterNode.rect.fLeft); @@ -179,6 +180,7 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi } FML_DLOG(INFO) << "Flutter_InitSpercificElementInfoById elementInfoFromList= "<(0)); //根据flutternode信息配置对应的elementinfo @@ -186,7 +188,7 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi //设置父节点id OH_ArkUI_SetAccessibilityElementInfoParentId(elementInfoFromList, -999); //设置无障碍播报文本 - std::string text4Announce = "这是flutter语义树的root节点"; + std::string text4Announce = "当前为root节点"; OH_ArkUI_SetAccessibilityElementInfoAccessibilityText(elementInfoFromList, text4Announce.c_str()); OH_ArkUI_SetAccessibilityElementInfoAccessibilityLevel(elementInfoFromList, "yes"); OH_ArkUI_SetAccessibilityElementInfoAccessibilityGroup(elementInfoFromList, false); @@ -229,9 +231,7 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi return; } - /** - * NOTE: 当elementid > 0时,进行节点属性的配置 - */ + /** NOTE: when elementId >= 1 */ //根据elementid获取对应的flutter节点 FML_DLOG(INFO) << "Flutter_InitSpercificElementInfoById elementId = "<(elementId)); @@ -242,7 +242,7 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi //设置父节点id int32_t parentId = GetParentId(elementId); if(parentId < 0) { - FML_DLOG(ERROR) << "Flutter_InitSpercificElementInfoById GetParentId is null"; + FML_DLOG(ERROR) << "Flutter_InitSpercificElementInfoById GetParentId is null, assigned to "< elementId="< Date: Wed, 11 Sep 2024 10:58:50 +0800 Subject: [PATCH 024/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E6=97=A0?= =?UTF-8?q?=E9=9A=9C=E7=A2=8Dbridge=E7=9A=84action=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 202 +++++++++++------- .../accessibility/ohos_accessibility_bridge.h | 2 + .../src/main/cpp/types/libflutter/index.d.ets | 2 + .../main/ets/embedding/engine/FlutterNapi.ets | 7 + shell/platform/ohos/library_loader.cpp | 3 + .../ohos/napi/platform_view_ohos_napi.cpp | 20 +- .../ohos/napi/platform_view_ohos_napi.h | 5 +- .../platform/ohos/ohos_xcomponent_adapter.cpp | 14 +- 8 files changed, 166 insertions(+), 89 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 5bdbc0a36c..b051ad4801 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -18,6 +18,7 @@ #include "ohos_accessibility_bridge.h" #include "flutter/shell/platform/ohos/ohos_shell_holder.h" +#define SHELL_HOLDER (reinterpret_cast(shell_holder)) namespace flutter { OhosAccessibilityBridge OhosAccessibilityBridge::bridgeInstance; @@ -33,12 +34,12 @@ OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() { void OhosAccessibilityBridge::announce(std::unique_ptr& message) { //创建并设置屏幕朗读事件 ArkUI_AccessibilityEventInfo* announceEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); - int32_t ret1 = OH_ArkUI_SetAccessibilityEventEventType(announceEventInfo, ArkUI_AccessibilityEventType::ARKUI_NATIVE_ACCESSIBILITY_TYPE_VIEW_ANNOUNCE_FOR_ACCESSIBILITY); + int32_t ret1 = OH_ArkUI_AccessibilityEventSetEventType(announceEventInfo, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ANNOUNCE_FOR_ACCESSIBILITY); if(ret1 != 0) { FML_DLOG(INFO) << "OhosAccessibilityBridge::announce OH_ArkUI_AccessibilityEventSetEventType failed"; return; } - int32_t ret2 = OH_ArkUI_SetAccessibilityEventTextAnnouncedForAccessibility(announceEventInfo, message.get()); + int32_t ret2 = OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility(announceEventInfo, message.get()); if(ret2 != 0) { FML_DLOG(INFO) << "OhosAccessibilityBridge::announce OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility failed"; return; @@ -86,7 +87,7 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree(ArkUI_AccessibilityElementI * FIXME: 这里先不统一将所有的elementinfos的全部属性进行配置,预先配置一些必要信息比如:id * 而是使用Flutter_InitSpercificElementInfoById对特定节点进行配置 * */ - OH_ArkUI_SetAccessibilityElementInfoElementId(elementInfo, flutterNode.id); + OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfo, flutterNode.id); //将当前flutter节点的全部子节点,创建每一个对应的childelementinfos并进行必要配置 int32_t childCount = static_cast(flutterNode.childrenInTraversalOrder.size()); @@ -97,7 +98,7 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree(ArkUI_AccessibilityElementI //加入父子节点id映射 <父节点id,子节点id> // parentChildIdMap.insert({flutterNode.id, childNodeIds[i]}); } - OH_ArkUI_SetAccessibilityElementInfoChildNodeIds(elementInfo, childCount, childNodeIds); + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfo, childCount, childNodeIds); //设置父节点id // if(!parentChildIdMap.size()) { @@ -105,25 +106,25 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree(ArkUI_AccessibilityElementI // return; // } int32_t parentId = GetParentId(flutterNode.id); - OH_ArkUI_SetAccessibilityElementInfoParentId(elementInfo, parentId); + OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, parentId); FML_DLOG(INFO) << "FlutterTreeToArkuiTree parent.id= "<(flutterNode.rect.fLeft); @@ -131,23 +132,23 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree(ArkUI_AccessibilityElementI int32_t right = static_cast(flutterNode.rect.fRight); int32_t bottom = static_cast(flutterNode.rect.fBottom); ArkUI_AccessibleRect rect = {left, top, right, bottom}; - OH_ArkUI_SetAccessibilityElementInfoScreenRect(elementInfo, &rect); + OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfo, &rect); //设置elementinfo的action类型 int32_t actionTypeNum = 3; ArkUI_AccessibleAction actions[actionTypeNum]; - actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS; + actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; actions[0].description = "flutter-ohos"; - actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; actions[1].description = "flutter-ohos"; - actions[2].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_LONG_CLICK; + actions[2].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK; actions[2].description = "flutter-ohos"; - OH_ArkUI_SetAccessibilityElementInfoOperationActions(elementInfo, actionTypeNum, actions); + OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfo, actionTypeNum, actions); //设置无障碍相关属性 - OH_ArkUI_SetAccessibilityElementInfoAccessibilityText(elementInfo, flutterNode.label.c_str()); - OH_ArkUI_SetAccessibilityElementInfoAccessibilityLevel(elementInfo, "yes"); - OH_ArkUI_SetAccessibilityElementInfoAccessibilityGroup(elementInfo, false); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfo, flutterNode.label.c_str()); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfo, "yes"); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfo, false); } FML_DLOG(ERROR)<<"FlutterTreeToArkuiTree is end"; } @@ -184,14 +185,14 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi if(elementId == 0 || elementId == -1) { flutter::SemanticsNode flutterNode = getOrCreateFlutterSemanticsNode(static_cast(0)); //根据flutternode信息配置对应的elementinfo - OH_ArkUI_SetAccessibilityElementInfoElementId(elementInfoFromList, 0); + OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, 0); //设置父节点id - OH_ArkUI_SetAccessibilityElementInfoParentId(elementInfoFromList, -999); + OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, -999); //设置无障碍播报文本 std::string text4Announce = "当前为root节点"; - OH_ArkUI_SetAccessibilityElementInfoAccessibilityText(elementInfoFromList, text4Announce.c_str()); - OH_ArkUI_SetAccessibilityElementInfoAccessibilityLevel(elementInfoFromList, "yes"); - OH_ArkUI_SetAccessibilityElementInfoAccessibilityGroup(elementInfoFromList, false); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfoFromList, text4Announce.c_str()); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes"); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, false); //配置child节点信息 int32_t childCount = static_cast(flutterNode.childrenInTraversalOrder.size()); @@ -200,17 +201,17 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi childNodeIds[i] = static_cast(flutterNode.childrenInTraversalOrder[i]); FML_DLOG(INFO) << "Flutter_InitSpercificElementInfoById -> elementid= "<<0<<" childCount= "<(flutterNode.rect.fLeft); @@ -218,16 +219,16 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi int32_t right = static_cast(flutterNode.rect.fRight); int32_t bottom = static_cast(flutterNode.rect.fBottom); ArkUI_AccessibleRect rect = {left, top, right, bottom}; - OH_ArkUI_SetAccessibilityElementInfoScreenRect(elementInfoFromList, &rect); + OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect); //设置elementinfo的action类型 int32_t actionTypeNum = 2; ArkUI_AccessibleAction actions[actionTypeNum]; - actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS; + actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; actions[0].description = "flutter-ohos"; - actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; actions[1].description = "flutter-ohos"; - OH_ArkUI_SetAccessibilityElementInfoOperationActions(elementInfoFromList, actionTypeNum, actions); + OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions); return; } @@ -237,21 +238,21 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi flutter::SemanticsNode flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); //根据flutternode信息配置对应的elementinfo - OH_ArkUI_SetAccessibilityElementInfoElementId(elementInfoFromList, flutterNode.id); + OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, flutterNode.id); //设置父节点id int32_t parentId = GetParentId(elementId); if(parentId < 0) { FML_DLOG(ERROR) << "Flutter_InitSpercificElementInfoById GetParentId is null, assigned to "<(flutterNode.childrenInTraversalOrder.size()); @@ -259,28 +260,28 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi for(int32_t i=0; i(flutterNode.childrenInTraversalOrder[i]); } - OH_ArkUI_SetAccessibilityElementInfoChildNodeIds(elementInfoFromList, childCount, childNodeIds); + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds); // 配置常用属性,force to true for debugging - OH_ArkUI_SetAccessibilityElementInfoClickable(elementInfoFromList, true); - OH_ArkUI_SetAccessibilityElementInfoCheckable(elementInfoFromList, true); - OH_ArkUI_SetAccessibilityElementInfoFocusable(elementInfoFromList, true); + OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); + OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true); + OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true); if(elementId == 4) { - OH_ArkUI_SetAccessibilityElementInfoFocused(elementInfoFromList, true); + OH_ArkUI_AccessibilityElementInfoSetFocused(elementInfoFromList, true); } - OH_ArkUI_SetAccessibilityElementInfoVisible(elementInfoFromList, true); - OH_ArkUI_SetAccessibilityElementInfoAccessibilityFocused(elementInfoFromList, true); - OH_ArkUI_SetAccessibilityElementInfoSelected(elementInfoFromList, true); - OH_ArkUI_SetAccessibilityElementInfoEnabled(elementInfoFromList, true); + OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused(elementInfoFromList, true); + OH_ArkUI_AccessibilityElementInfoSetSelected(elementInfoFromList, true); + OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true); //FIXME: 元素所属的组件类型(如:root, button,text等) std::string componentTypeName = GetNodeComponentType(flutterNode); if(elementId == 0) { - OH_ArkUI_SetAccessibilityElementInfoComponentType(elementInfoFromList, "root"); + OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root"); } else if(elementId == 4) { - OH_ArkUI_SetAccessibilityElementInfoComponentType(elementInfoFromList, componentTypeName.c_str()); + OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, componentTypeName.c_str()); } else { - OH_ArkUI_SetAccessibilityElementInfoComponentType(elementInfoFromList, componentTypeName.c_str()); + OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, componentTypeName.c_str()); } FML_DLOG(INFO) << "Flutter_InitSpercificElementInfoById OH_ArkUI_SetAccessibilityElementInfoComponentType = "<(flutterNode.rect.fRight); int32_t bottom = static_cast(flutterNode.rect.fBottom); ArkUI_AccessibleRect rect = {left, top, right, bottom}; - OH_ArkUI_SetAccessibilityElementInfoScreenRect(elementInfoFromList, &rect); + OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect); //无障碍重要性,用于控制某个组件是否可被无障碍辅助服务所识别。支持的值为: // “auto”:根据组件不同会转换为“yes”或者“no”。 @@ -298,20 +299,20 @@ void OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById(ArkUI_Accessi // “no”:当前组件不可被无障碍辅助服务所识别。 // “no-hide-descendants”:当前组件及其所有子组件不可被无障碍辅助服务所识别。 // 默认值:“auto” - OH_ArkUI_SetAccessibilityElementInfoAccessibilityLevel(elementInfoFromList, "yes"); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes"); //无障碍组,设置为true时表示该组件及其所有子组件为一整个可以选中的组件,无障碍服务将不再关注其子组件内容。默认值:false - OH_ArkUI_SetAccessibilityElementInfoAccessibilityGroup(elementInfoFromList, false); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, false); //设置elementinfo的action类型 int32_t actionTypeNum = 3; ArkUI_AccessibleAction actions[actionTypeNum]; - actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS; + actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; actions[0].description = "flutter-ohos"; - actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; actions[1].description = "flutter-ohos"; - actions[2].actionType = ArkUI_Accessibility_ActionType::ARKUI_NATIVE_ACCESSIBILITY_ACTION_CLICK; + actions[2].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; actions[2].description = "flutter-ohos"; - OH_ArkUI_SetAccessibilityElementInfoOperationActions(elementInfoFromList, actionTypeNum, actions); + OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions); FML_DLOG(INFO) << "OhosAccessibilityBridge::Flutter_InitSpercificElementInfoById is end"; } @@ -329,23 +330,22 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( FML_DLOG(INFO) << "#### FindAccessibilityNodeInfosById input-params ####: elementId = "<(flutterSemanticsTree_.size()); @@ -354,22 +354,22 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( // Flutter_InitSpercificElementInfoById(newElementInfo, i); // } - } else if(mode == ArkUI_AccessibilitySearchMode::NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS) { + } else if(mode == ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS) { /** Search for parent nodes. (mode = 1) */ Flutter_InitSpercificElementInfoById(elementInfoFromList, elementId); FlutterTreeToArkuiTree(elementList); - } else if(mode == ArkUI_AccessibilitySearchMode::NATIVE_SEARCH_MODE_PREFETCH_SIBLINGS) { + } else if(mode == ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_SIBLINGS) { /** Search for sibling nodes. (mode = 2) */ Flutter_InitSpercificElementInfoById(elementInfoFromList, elementId); FlutterTreeToArkuiTree(elementList); - } else if(mode == ArkUI_AccessibilitySearchMode::NATIVE_SEARCH_MODE_PREFETCH_CHILDREN) { + } else if(mode == ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CHILDREN) { /** Search for child nodes at the next level. (mode = 4) */ Flutter_InitSpercificElementInfoById(elementInfoFromList, elementId); FlutterTreeToArkuiTree(elementList); - } else if(mode == ArkUI_AccessibilitySearchMode::NATIVE_SEARCH_MODE_PREFETCH_RECURSIVE_CHILDREN) { + } else if(mode == ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_RECURSIVE_CHILDREN) { /** Search for all child nodes. (mode = 8) */ Flutter_InitSpercificElementInfoById(elementInfoFromList, elementId); int64_t elementInfoCount = static_cast(flutterSemanticsTree_.size()); @@ -383,7 +383,7 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( } FML_DLOG(INFO) << "--- FindAccessibilityNodeInfosById is end ---"; - return OH_ARKUI_ACCESSIBILITY_RESULT_SUCCESS; + return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; } /** Called to obtain element information based on a specified node and text @@ -417,8 +417,50 @@ int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( return 0; } -void DispatchSemanticsAction(int32_t id, flutter::SemanticsAction action) { +/** 将arkui的action类型转化为flutter的action类型 */ +int32_t ActionTypeConversion(ArkUI_Accessibility_ActionType arkui_action) { + //部分arkui操作和flutter操作的映射,其余action暂时无法适配, 这里先return 0 + switch(arkui_action) { + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: + return static_cast(ACTIONS_::kTap); + + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: + return static_cast(ACTIONS_::kLongPress); + + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: + return static_cast(ACTIONS_::kScrollUp); + + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: + return static_cast(ACTIONS_::kScrollDown); + + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: + return static_cast(ACTIONS_::kCopy); + + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: + return static_cast(ACTIONS_::kCut); + + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: + return static_cast(ACTIONS_::kDidGainAccessibilityFocus); + + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: + return static_cast(ACTIONS_::kDidLoseAccessibilityFocus); + + //Text selection action, requiring the setting of selectTextBegin, TextEnd, and TextInForward + //parameters to select a text segment in the text box. */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: + return static_cast(ACTIONS_::kSetSelection); + + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: + return static_cast(ACTIONS_::kSetText); + + default: + return static_cast(ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID); + } +} +void DispatchSemanticsAction(int32_t id, flutter::SemanticsAction action ) { + FML_DLOG(INFO)<<"DispatchSemanticsAction is called"; + // SHELL_HOLDER->GetPlatformView()->DispatchSemanticsAction(id, action, {}); } /** @@ -434,7 +476,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( if(actionArguments == nullptr) { FML_DLOG(ERROR)<<"OhosAccessibilityBridge::ExecuteAccessibilityAction actionArguments = null"; - return OH_ARKUI_ACCESSIBILITY_RESULT_FAILED; + return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } // std::string key = "click"; @@ -442,17 +484,17 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( // OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key.c_str(), &value); // if(value == nullptr) { // FML_DLOG(ERROR)<<"ExecuteAccessibilityAction OH_ArkUI_FindAccessibilityActionArgumentByKey value = null"; - // return OH_ARKUI_ACCESSIBILITY_RESULT_FAILED; + // return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; // } else { // FML_DLOG(INFO)<<"ExecuteAccessibilityAction OH_ArkUI_FindAccessibilityActionArgumentByKey value ="< void; export const nativeAnnounce: (message: string) => void; export const nativeSetSemanticsEnabled: (nativeShellHolderId: number, enabled: boolean) => void; + +export const nativeGetShellHolderId: (nativeShellHolderId: number) => void; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index b2ec0b7df0..d8988d3317 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -507,6 +507,13 @@ export default class FlutterNapi { } } + getShellHolderId(): void { + this.ensureRunningOnMainThread(); + if (this.isAttached()) { + flutter.nativeGetShellHolderId(this.nativeShellHolderId!); + } + } + } export interface AccessibilityDelegate { diff --git a/shell/platform/ohos/library_loader.cpp b/shell/platform/ohos/library_loader.cpp index 3c0ab4ff88..d25da5085e 100644 --- a/shell/platform/ohos/library_loader.cpp +++ b/shell/platform/ohos/library_loader.cpp @@ -148,6 +148,9 @@ static napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_FUNCTION( "nativeSetSemanticsEnabled", flutter::PlatformViewOHOSNapi::nativeSetSemanticsEnabled), + DECLARE_NAPI_FUNCTION( + "nativeGetShellHolderId", + flutter::PlatformViewOHOSNapi::nativeGetShellHolderId), }; FML_DLOG(INFO) << "Init NAPI size=" << sizeof(desc) / sizeof(desc[0]); diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index 5cf0548cf2..0501fd36b2 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1903,9 +1903,27 @@ napi_value PlatformViewOHOSNapi::nativeSetSemanticsEnabled(napi_env env, napi_ca return nullptr; } OHOS_SHELL_HOLDER->GetPlatformView()->SetSemanticsEnabled(enabled); - FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeSetSemanticsEnabled " + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeSetSemanticsEnabled " "OHOS_SHELL_HOLDER->GetPlatformView()->SetSemanticsEnabled= "<nativeShellHolder = shell_holder; + return nullptr; +} + } // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h index f6597f35ad..6b82270e06 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.h +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -184,7 +184,7 @@ class PlatformViewOHOSNapi { int32_t height); static void SurfaceDestroyed(int64_t shell_holder); - static int64_t GetShellHolder(); + static napi_value nativeXComponentAttachFlutterEngine( napi_env env, napi_callback_info info); @@ -213,6 +213,9 @@ class PlatformViewOHOSNapi { static napi_value nativeSetSemanticsEnabled( napi_env env, napi_callback_info info); + static napi_value nativeGetShellHolderId( + napi_env env, + napi_callback_info info); private: static napi_env env_; diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp index c8df5699f5..f5c19bdbf0 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.cpp +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -352,13 +352,13 @@ int32_t GetAccessibilityNodeCursorPosition( } void XComponentBase::BindAccessibilityProviderCallback() { - accessibilityProviderCallback_.FindAccessibilityNodeInfosById = FindAccessibilityNodeInfosById; - accessibilityProviderCallback_.FindAccessibilityNodeInfosByText = FindAccessibilityNodeInfosByText; - accessibilityProviderCallback_.FindFocusedAccessibilityNode = FindFocusedAccessibilityNode; - accessibilityProviderCallback_.FindNextFocusAccessibilityNode = FindNextFocusAccessibilityNode; - accessibilityProviderCallback_.ExecuteAccessibilityAction = ExecuteAccessibilityAction; - accessibilityProviderCallback_.ClearFocusedFocusAccessibilityNode = ClearFocusedFocusAccessibilityNode; - accessibilityProviderCallback_.GetAccessibilityNodeCursorPosition = GetAccessibilityNodeCursorPosition; + accessibilityProviderCallback_.findAccessibilityNodeInfosById = FindAccessibilityNodeInfosById; + accessibilityProviderCallback_.findAccessibilityNodeInfosByText = FindAccessibilityNodeInfosByText; + accessibilityProviderCallback_.findFocusedAccessibilityNode = FindFocusedAccessibilityNode; + accessibilityProviderCallback_.findNextFocusAccessibilityNode = FindNextFocusAccessibilityNode; + accessibilityProviderCallback_.executeAccessibilityAction = ExecuteAccessibilityAction; + accessibilityProviderCallback_.clearFocusedFocusAccessibilityNode = ClearFocusedFocusAccessibilityNode; + accessibilityProviderCallback_.getAccessibilityNodeCursorPosition = GetAccessibilityNodeCursorPosition; } XComponentBase::XComponentBase(std::string id){ -- Gitee From d31c9c214141471d1a466b47798d18316f04358b Mon Sep 17 00:00:00 2001 From: zjxi Date: Sun, 15 Sep 2024 17:12:33 +0800 Subject: [PATCH 025/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E6=97=A0?= =?UTF-8?q?=E9=9A=9C=E7=A2=8D=E8=AF=AD=E4=B9=89=E6=A0=91=E7=9A=84=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E8=8A=82=E7=82=B9=E7=9B=B8=E5=AF=B9=E5=9D=90=E6=A0=87?= =?UTF-8?q?=E8=BD=AC=E5=8C=96=E5=B1=8F=E5=B9=95=E7=BB=9D=E5=AF=B9=E5=9D=90?= =?UTF-8?q?=E6=A0=87=E7=9A=84=E6=98=A0=E5=B0=84=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- lib/ui/semantics/semantics_update_builder.cc | 2 + .../ohos_accessibility_bridge.cpp | 453 ++++++++++++------ .../accessibility/ohos_accessibility_bridge.h | 11 +- 3 files changed, 314 insertions(+), 152 deletions(-) diff --git a/lib/ui/semantics/semantics_update_builder.cc b/lib/ui/semantics/semantics_update_builder.cc index 595ecf85f7..75c9a6274e 100644 --- a/lib/ui/semantics/semantics_update_builder.cc +++ b/lib/ui/semantics/semantics_update_builder.cc @@ -103,7 +103,9 @@ void SemanticsUpdateBuilder::updateNode( SkScalar scalarTransform[16]; for (int i = 0; i < 16; ++i) { scalarTransform[i] = transform.data()[i]; + FML_DLOG(INFO) << "999 node.id="<(shell_holder)) namespace flutter { @@ -83,32 +86,48 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree(ArkUI_AccessibilityElementI "elementInfo is null"; return; } - /** - * FIXME: 这里先不统一将所有的elementinfos的全部属性进行配置,预先配置一些必要信息比如:id - * 而是使用Flutter_InitSpercificElementInfoById对特定节点进行配置 - * */ + //设置elementinfo的屏幕坐标范围 + int32_t left = static_cast(flutterNode.rect.fLeft); + int32_t top = static_cast(flutterNode.rect.fTop); + int32_t right = static_cast(flutterNode.rect.fRight); + int32_t bottom = static_cast(flutterNode.rect.fBottom); + ArkUI_AccessibleRect rect = {left, top, right, bottom}; + OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfo, &rect); + + //设置elementinfo的action类型 + int32_t actionTypeNum = 3; + ArkUI_AccessibleAction actions[actionTypeNum]; + actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; + actions[0].description = "获取焦点动作事件"; + actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].description = "清除焦点动作事件"; + actions[2].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; + actions[2].description = "点击动作事件"; + OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfo, actionTypeNum, actions); + + //设置elementid OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfo, flutterNode.id); - //将当前flutter节点的全部子节点,创建每一个对应的childelementinfos并进行必要配置 + //设置父节点id + int32_t parentId = GetParentId(flutterNode.id); + if(flutterNode.id == 0) { + OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, -2100000); + FML_DLOG(INFO) << "FlutterTreeToArkuiTree parent.id= "<(flutterNode.rect.fLeft); - int32_t top = static_cast(flutterNode.rect.fTop); - int32_t right = static_cast(flutterNode.rect.fRight); - int32_t bottom = static_cast(flutterNode.rect.fBottom); - ArkUI_AccessibleRect rect = {left, top, right, bottom}; - OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfo, &rect); - - //设置elementinfo的action类型 - int32_t actionTypeNum = 3; - ArkUI_AccessibleAction actions[actionTypeNum]; - actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; - actions[0].description = "flutter-ohos"; - actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; - actions[1].description = "flutter-ohos"; - actions[2].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK; - actions[2].description = "flutter-ohos"; - OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfo, actionTypeNum, actions); + std::string contents = componentTypeName + "_content"; + OH_ArkUI_AccessibilityElementInfoSetContents(elementInfo, contents.c_str()); //设置无障碍相关属性 OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfo, flutterNode.label.c_str()); OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfo, "yes"); OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfo, false); } - FML_DLOG(ERROR)<<"FlutterTreeToArkuiTree is end"; + FML_DLOG(INFO)<<"FlutterTreeToArkuiTree is end"; } /** * 获取当前elementid的父节点id */ int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) { - int32_t childElementId = static_cast(elementId); - if(!parentChildIdMap.size()) { - FML_DLOG(INFO) << "OhosAccessibilityBridge::GetParentId parentChildIdMap.size()=0"; - return -2; + int32_t childElementId = static_cast(elementId); + if(!parentChildIdVec.size()) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::GetParentId parentChildIdMap.size()=0"; + return -2100000; + } + for(const auto& item: parentChildIdVec) { + if(item.second == childElementId) { + return item.first; } - for(const auto& item: parentChildIdMap) { - if(item.second == childElementId) { - return item.first; - } + } + return -2100000; +} + +/** + * 设置并获取xcomponet上渲染的组件的画框的绝对坐标rect + */ +void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, float left, float top, float right, float bottom) { + if(screenRectMap_.find(flutterNodeId) == screenRectMap_.end()) { + screenRectMap_.insert({flutterNodeId, std::make_pair(std::make_pair(left, top), std::make_pair(right, bottom))}); + FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { "< } is succeed"; + } else { + FML_DLOG(ERROR) << "SetAbsoluteScreenRect -> flutterNodeId="<, std::pair> OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) { + if(!screenRectMap_.empty() && screenRectMap_.count(flutterNodeId) > 0) { + return screenRectMap_.at(flutterNodeId); + } else { + FML_DLOG(ERROR) << "GetAbsoluteScreenRect -> flutterNodeId="<(currNode.rect.fLeft); + auto currTop = static_cast(currNode.rect.fTop); + auto currRight = static_cast(currNode.rect.fRight); + auto currBottom = static_cast(currNode.rect.fBottom); + + //获取当前flutter节点的缩放、平移、透视等矩阵坐标转换 + SkMatrix transform = currNode.transform.asM33(); + auto _kMScaleX = transform.get(SkMatrix::kMScaleX); + auto _kMTransX = transform.get(SkMatrix::kMTransX); + auto _kMScaleY = transform.get(SkMatrix::kMScaleY); + auto _kMTransY = transform.get(SkMatrix::kMTransY); + /** 以下矩阵坐标变换参数(如:旋转/错切、透视)场景目前暂不考虑 */ + // auto _kMSkewX = transform.get(SkMatrix::kMSkewX); + // auto _kMSkewY = transform.get(SkMatrix::kMSkewY); + // auto _kMPersp0 = transform.get(SkMatrix::kMPersp0); + // auto _kMPersp1 = transform.get(SkMatrix::kMPersp1); + // auto _kMPersp2 = transform.get(SkMatrix::kMPersp2); + + //获取当前flutter节点的父节点的相对rect + int32_t parentId = GetParentId(currNode.id); + auto parentNode = getOrCreateFlutterSemanticsNode(parentId); + // auto parentLeft = parentNode.rect.fLeft; + // auto parentTop = parentNode.rect.fTop; + auto parentRight = parentNode.rect.fRight; + auto parentBottom = parentNode.rect.fBottom; + + //获取当前flutter节点的父节点的绝对坐标 + auto _rectPairs = GetAbsoluteScreenRect(parentNode.id); + auto realParentLeft = _rectPairs.first.first; + auto realParentTop = _rectPairs.first.second; + auto realParentRight = _rectPairs.second.first; + auto realParentBottom = _rectPairs.second.second; + + //真实缩放系数 + float realScaleFactor = realParentRight / parentRight * 1.0; + // float xOffset = realParentLeft; + // float yOffset = realParentTop; + float newLeft, newTop, newRight, newBottom; + + if(_kMScaleX > 1 && _kMScaleY > 1 ) { + //子节点相对父节点进行变化(常用的缩放、 平移) + newLeft = currLeft + _kMTransX * _kMScaleX; + newTop = currTop + _kMTransY * _kMScaleY; + newRight = currRight * _kMScaleX; + newBottom = currBottom * _kMScaleY; + //更新当前flutter节点currNode的相对坐标 -> 屏幕绝对坐标 + SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); + FML_DLOG(INFO) << "ConvertChildRelativeRectToSceenRect -> { nodeId: "< { nodeId: "<(flutterNode.childrenInTraversalOrder[i]); - FML_DLOG(INFO) << "Flutter_InitSpercificElementInfoById -> elementid= "<<0<<" childCount= "< elementid=0 childCount="<(flutterNode.rect.fLeft); - int32_t top = static_cast(flutterNode.rect.fTop); - int32_t right = static_cast(flutterNode.rect.fRight); - int32_t bottom = static_cast(flutterNode.rect.fBottom); - ArkUI_AccessibleRect rect = {left, top, right, bottom}; - OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect); - - //设置elementinfo的action类型 - int32_t actionTypeNum = 2; - ArkUI_AccessibleAction actions[actionTypeNum]; - actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; - actions[0].description = "flutter-ohos"; - actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; - actions[1].description = "flutter-ohos"; - OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions); return; } - /** NOTE: when elementId >= 1 */ + /** ----------------------------------------------- NOTE: when elementId >= 1 -------------------------------------------- */ //根据elementid获取对应的flutter节点 - FML_DLOG(INFO) << "Flutter_InitSpercificElementInfoById elementId = "< node.id= "< elementid="< arkui语义节点树 + // FlutterTreeToArkuiTree(elementList); + if(mode == ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { /** Search for current nodes. (mode = 0) */ - Flutter_InitSpercificElementInfoById(elementInfoFromList, elementId); + FlutterNodeToElementInfoById(elementInfoFromList, elementId); + int64_t elementInfoCount = static_cast(flutterSemanticsTree_.size()); + for(int64_t i=1; i(flutterSemanticsTree_.size()); // for(int64_t i=1; i(flutterSemanticsTree_.size()); + // for(int64_t i=1; i(flutterSemanticsTree_.size()); + // for(int64_t i=1; i(flutterSemanticsTree_.size()); for(int64_t i=1; i visitedObjs; // SEMANTICS_NODE_ rootObj = getRootSemanticsNode(); std::vector newRoutes; @@ -659,8 +793,9 @@ void OhosAccessibilityBridge::updateSemantics( // todo:获取当前节点的全部子节点数量,并构建当前节点的全部更新子节点 int32_t childNodeCount = node.childrenInTraversalOrder.size(); for (int32_t i = 0; i < childNodeCount; i++) { - parentChildIdMap.insert({node.id, node.childrenInTraversalOrder[i]}); - FML_DLOG(INFO) <<"UpdateSemantics parentChildIdMap.insert{"< ("< {"< ("< flutterSemanticsTree_.size()=0"; + FML_DLOG(ERROR)<<"getFlutterRootSemanticsNode -> flutterSemanticsTree_.size()=0"; return flutter::SemanticsNode{}; } + if(flutterSemanticsTree_.find(0) == flutterSemanticsTree_.end()) { + FML_DLOG(ERROR)<<"getFlutterRootSemanticsNode -> flutterSemanticsTree_ has no keys = 0"; + return flutter::SemanticsNode{}; + } return flutterSemanticsTree_.at(0); } @@ -847,13 +993,20 @@ void OhosAccessibilityBridge::removeSemanticsNode( void OhosAccessibilityBridge::printTest(flutter::SemanticsNode node) { FML_DLOG(INFO) << "==================SemanticsNode====================="; + SkMatrix _transform = node.transform.asM33(); FML_DLOG(INFO) << "node.id=" << node.id; FML_DLOG(INFO) << "node.flags=" << node.flags; FML_DLOG(INFO) << "node.actions=" << node.actions; - FML_DLOG(INFO) << "node.rect.left=" << node.rect.fLeft; - FML_DLOG(INFO) << "node.rect.top=" << node.rect.fTop; - FML_DLOG(INFO) << "node.rect.right=" << node.rect.fRight; - FML_DLOG(INFO) << "node.rect.bottom=" << node.rect.fBottom; + FML_DLOG(INFO) << "node.rect= {" << node.rect.fLeft<<", "< kMScaleX=" << _transform.get(SkMatrix::kMScaleX); + FML_DLOG(INFO) << "node.transform -> kMSkewX=" << _transform.get(SkMatrix::kMSkewX); + FML_DLOG(INFO) << "node.transform -> kMTransX=" << _transform.get(SkMatrix::kMTransX); + FML_DLOG(INFO) << "node.transform -> kMSkewY=" << _transform.get(SkMatrix::kMSkewY); + FML_DLOG(INFO) << "node.transform -> kMScaleY=" << _transform.get(SkMatrix::kMScaleY); + FML_DLOG(INFO) << "node.transform -> kMTransY=" << _transform.get(SkMatrix::kMTransY); + FML_DLOG(INFO) << "node.transform -> kMPersp0=" << _transform.get(SkMatrix::kMPersp0); + FML_DLOG(INFO) << "node.transform -> kMPersp1=" << _transform.get(SkMatrix::kMPersp1); + FML_DLOG(INFO) << "node.transform -> kMPersp2=" << _transform.get(SkMatrix::kMPersp2); FML_DLOG(INFO) << "node.maxValueLength=" << node.maxValueLength; FML_DLOG(INFO) << "node.currentValueLength=" << node.currentValueLength; FML_DLOG(INFO) << "node.textSelectionBase=" << node.textSelectionBase; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 4aa3afd9ad..3fdee2ca8c 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "flutter/fml/log_level.h" @@ -27,6 +28,7 @@ #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_manager.h" #include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" + namespace flutter { typedef flutter::SemanticsFlags FLAGS_; @@ -66,15 +68,20 @@ class OhosAccessibilityBridge { ArkUI_AccessibilityProvider* provider_; void Flutter_SendAccessibilityAsyncEvent(int64_t elementId, ArkUI_AccessibilityEventType eventType); - void Flutter_InitSpercificElementInfoById(ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId); + void FlutterNodeToElementInfoById(ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId); int32_t GetParentId(int64_t elementId); + void ConvertChildRelativeRectToSceenRect(flutter::SemanticsNode node); + std::pair, std::pair> GetAbsoluteScreenRect(int32_t flutterNodeId); + void SetAbsoluteScreenRect(int32_t flutterNodeId, float left, float top, float right, float bottom); + private: static OhosAccessibilityBridge bridgeInstance; std::shared_ptr ax_manager_; - std::unordered_map parentChildIdMap; + std::vector> parentChildIdVec; std::unordered_map flutterSemanticsTree_; + std::unordered_map, std::pair>> screenRectMap_; std::unordered_map actions_mp_; std::vector flutterNavigationStack; -- Gitee From 27415ae3785ae23ffdc43a569e66d9f2df5b7f86 Mon Sep 17 00:00:00 2001 From: zjxi Date: Sun, 15 Sep 2024 18:23:08 +0800 Subject: [PATCH 026/151] =?UTF-8?q?refactor:=E9=87=8D=E6=9E=84=E9=83=A8?= =?UTF-8?q?=E5=88=86=E4=BB=A3=E7=A0=81=EF=BC=8C=E5=AE=8C=E5=96=84=E8=A7=84?= =?UTF-8?q?=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos/accessibility/ohos_accessibility_bridge.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 095ca22e9a..8188291f42 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -172,7 +172,7 @@ int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) { } /** - * 设置并获取xcomponet上渲染的组件的画框的绝对坐标rect + * 设置并获取xcomponet上渲染的组件的屏幕绝对坐标rect */ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, float left, float top, float right, float bottom) { if(screenRectMap_.find(flutterNodeId) == screenRectMap_.end()) { @@ -193,7 +193,8 @@ std::pair, std::pair> OhosAccessibilityBri } /** - * flutter语义节点的子节点相对父节点坐标的矩阵变换,并返回转换后绝对屏幕坐标的rect + * flutter无障碍语义树的子节点相对坐标系转化为屏幕绝对坐标的映射算法 + * TODO: 当前算法流程为初期版本,需要完善优化(目前暂未考虑旋转、透视场景) */ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect(flutter::SemanticsNode currNode) { //获取当前flutter节点的相对rect @@ -232,8 +233,6 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect(flutter::Seman //真实缩放系数 float realScaleFactor = realParentRight / parentRight * 1.0; - // float xOffset = realParentLeft; - // float yOffset = realParentTop; float newLeft, newTop, newRight, newBottom; if(_kMScaleX > 1 && _kMScaleY > 1 ) { @@ -244,7 +243,6 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect(flutter::Seman newBottom = currBottom * _kMScaleY; //更新当前flutter节点currNode的相对坐标 -> 屏幕绝对坐标 SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); - FML_DLOG(INFO) << "ConvertChildRelativeRectToSceenRect -> { nodeId: "< { nodeId: "< { nodeId: "<GetPlatformView()->DispatchSemanticsAction(id, action, {}); } -- Gitee From 776439e50016bb399dd3cdc95a97075f2d491b18 Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 18 Sep 2024 16:18:20 +0800 Subject: [PATCH 027/151] =?UTF-8?q?feat:=E4=BC=98=E5=8C=96=E9=83=A8?= =?UTF-8?q?=E5=88=86=E6=97=A0=E9=9A=9C=E7=A2=8D=E5=8A=9F=E8=83=BD=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E6=A0=BC=E5=BC=8F=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 930 +++++++++++------- 1 file changed, 566 insertions(+), 364 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 8188291f42..dde1a24db8 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -13,18 +13,18 @@ * limitations under the License. */ +#include "ohos_accessibility_bridge.h" #include #include "flutter/fml/logging.h" -#include "ohos_accessibility_bridge.h" +#include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/ohos/ohos_shell_holder.h" -#include "third_party/skia/include/core/SkScalar.h" #include "third_party/skia/include/core/SkMatrix.h" -#include "flutter/shell/platform/embedder/embedder.h" +#include "third_party/skia/include/core/SkScalar.h" #define SHELL_HOLDER (reinterpret_cast(shell_holder)) namespace flutter { -OhosAccessibilityBridge OhosAccessibilityBridge::bridgeInstance; +OhosAccessibilityBridge OhosAccessibilityBridge::bridgeInstance; OhosAccessibilityBridge::OhosAccessibilityBridge() {}; OhosAccessibilityBridge::~OhosAccessibilityBridge() {}; @@ -33,19 +33,26 @@ OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() { return &OhosAccessibilityBridge::bridgeInstance; } - void OhosAccessibilityBridge::announce(std::unique_ptr& message) { - //创建并设置屏幕朗读事件 - ArkUI_AccessibilityEventInfo* announceEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); - int32_t ret1 = OH_ArkUI_AccessibilityEventSetEventType(announceEventInfo, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ANNOUNCE_FOR_ACCESSIBILITY); - if(ret1 != 0) { - FML_DLOG(INFO) << "OhosAccessibilityBridge::announce OH_ArkUI_AccessibilityEventSetEventType failed"; - return; + // 创建并设置屏幕朗读事件 + ArkUI_AccessibilityEventInfo* announceEventInfo = + OH_ArkUI_CreateAccessibilityEventInfo(); + int32_t ret1 = OH_ArkUI_AccessibilityEventSetEventType( + announceEventInfo, + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ANNOUNCE_FOR_ACCESSIBILITY); + if (ret1 != 0) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::announce " + "OH_ArkUI_AccessibilityEventSetEventType failed"; + return; } - int32_t ret2 = OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility(announceEventInfo, message.get()); - if(ret2 != 0) { - FML_DLOG(INFO) << "OhosAccessibilityBridge::announce OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility failed"; - return; + int32_t ret2 = OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility( + announceEventInfo, message.get()); + if (ret2 != 0) { + FML_DLOG(INFO) + << "OhosAccessibilityBridge::announce " + "OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility failed"; + return; } FML_DLOG(INFO) << ("OhosAccessibilityBridge::announce message: ") << (message.get()); @@ -60,9 +67,10 @@ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode( flutter::SemanticsNode node; if (flutterSemanticsTree_.count(id) > 0) { return flutterSemanticsTree_.at(id); - FML_DLOG(INFO)<<"getOrCreateFlutterSemanticsNode get node.id="<(flutterNode.rect.fLeft); - int32_t top = static_cast(flutterNode.rect.fTop); + int32_t top = static_cast(flutterNode.rect.fTop); int32_t right = static_cast(flutterNode.rect.fRight); - int32_t bottom = static_cast(flutterNode.rect.fBottom); - ArkUI_AccessibleRect rect = {left, top, right, bottom}; + int32_t bottom = static_cast(flutterNode.rect.fBottom); + ArkUI_AccessibleRect rect = {left, top, right, bottom}; OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfo, &rect); - //设置elementinfo的action类型 + // 设置elementinfo的action类型 int32_t actionTypeNum = 3; ArkUI_AccessibleAction actions[actionTypeNum]; - actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; + actions[0].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; actions[0].description = "获取焦点动作事件"; - actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; actions[1].description = "清除焦点动作事件"; - actions[2].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; + actions[2].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; actions[2].description = "点击动作事件"; - OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfo, actionTypeNum, actions); + OH_ArkUI_AccessibilityElementInfoSetOperationActions( + elementInfo, actionTypeNum, actions); - //设置elementid + // 设置elementid OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfo, flutterNode.id); - //设置父节点id + // 设置父节点id int32_t parentId = GetParentId(flutterNode.id); - if(flutterNode.id == 0) { + if (flutterNode.id == 0) { OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, -2100000); - FML_DLOG(INFO) << "FlutterTreeToArkuiTree parent.id= "<(elementId); - if(!parentChildIdVec.size()) { - FML_DLOG(INFO) << "OhosAccessibilityBridge::GetParentId parentChildIdMap.size()=0"; + if (!parentChildIdVec.size()) { + FML_DLOG(INFO) + << "OhosAccessibilityBridge::GetParentId parentChildIdMap.size()=0"; return -2100000; } - for(const auto& item: parentChildIdVec) { - if(item.second == childElementId) { + for (const auto& item : parentChildIdVec) { + if (item.second == childElementId) { return item.first; } } @@ -174,20 +192,31 @@ int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) { /** * 设置并获取xcomponet上渲染的组件的屏幕绝对坐标rect */ -void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, float left, float top, float right, float bottom) { - if(screenRectMap_.find(flutterNodeId) == screenRectMap_.end()) { - screenRectMap_.insert({flutterNodeId, std::make_pair(std::make_pair(left, top), std::make_pair(right, bottom))}); - FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { "< } is succeed"; - } else { - FML_DLOG(ERROR) << "SetAbsoluteScreenRect -> flutterNodeId="< insert { " << flutterNodeId + << ", <" << left << ", " << top << ", " << right << ", " + << bottom << "> } is succeed"; + } else { + FML_DLOG(ERROR) << "SetAbsoluteScreenRect -> flutterNodeId=" + << flutterNodeId << " already exists !"; + } } -std::pair, std::pair> OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) { - if(!screenRectMap_.empty() && screenRectMap_.count(flutterNodeId) > 0) { +std::pair, std::pair> +OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) { + if (!screenRectMap_.empty() && screenRectMap_.count(flutterNodeId) > 0) { return screenRectMap_.at(flutterNodeId); } else { - FML_DLOG(ERROR) << "GetAbsoluteScreenRect -> flutterNodeId="< flutterNodeId=" + << flutterNodeId << " is not found !"; return {}; } } @@ -196,14 +225,15 @@ std::pair, std::pair> OhosAccessibilityBri * flutter无障碍语义树的子节点相对坐标系转化为屏幕绝对坐标的映射算法 * TODO: 当前算法流程为初期版本,需要完善优化(目前暂未考虑旋转、透视场景) */ -void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect(flutter::SemanticsNode currNode) { - //获取当前flutter节点的相对rect +void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( + flutter::SemanticsNode currNode) { + // 获取当前flutter节点的相对rect auto currLeft = static_cast(currNode.rect.fLeft); auto currTop = static_cast(currNode.rect.fTop); auto currRight = static_cast(currNode.rect.fRight); auto currBottom = static_cast(currNode.rect.fBottom); - //获取当前flutter节点的缩放、平移、透视等矩阵坐标转换 + // 获取当前flutter节点的缩放、平移、透视等矩阵坐标转换 SkMatrix transform = currNode.transform.asM33(); auto _kMScaleX = transform.get(SkMatrix::kMScaleX); auto _kMTransX = transform.get(SkMatrix::kMTransX); @@ -216,103 +246,120 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect(flutter::Seman // auto _kMPersp1 = transform.get(SkMatrix::kMPersp1); // auto _kMPersp2 = transform.get(SkMatrix::kMPersp2); - //获取当前flutter节点的父节点的相对rect + // 获取当前flutter节点的父节点的相对rect int32_t parentId = GetParentId(currNode.id); - auto parentNode = getOrCreateFlutterSemanticsNode(parentId); + auto parentNode = getOrCreateFlutterSemanticsNode(parentId); // auto parentLeft = parentNode.rect.fLeft; // auto parentTop = parentNode.rect.fTop; auto parentRight = parentNode.rect.fRight; - auto parentBottom = parentNode.rect.fBottom; + auto parentBottom = parentNode.rect.fBottom; - //获取当前flutter节点的父节点的绝对坐标 + // 获取当前flutter节点的父节点的绝对坐标 auto _rectPairs = GetAbsoluteScreenRect(parentNode.id); auto realParentLeft = _rectPairs.first.first; - auto realParentTop = _rectPairs.first.second; + auto realParentTop = _rectPairs.first.second; auto realParentRight = _rectPairs.second.first; - auto realParentBottom = _rectPairs.second.second; + auto realParentBottom = _rectPairs.second.second; - //真实缩放系数 + // 真实缩放系数 float realScaleFactor = realParentRight / parentRight * 1.0; float newLeft, newTop, newRight, newBottom; - if(_kMScaleX > 1 && _kMScaleY > 1 ) { - //子节点相对父节点进行变化(常用的缩放、 平移) - newLeft = currLeft + _kMTransX * _kMScaleX; - newTop = currTop + _kMTransY * _kMScaleY; - newRight = currRight * _kMScaleX; + if (_kMScaleX > 1 && _kMScaleY > 1) { + // 子节点相对父节点进行变化(缩放、 平移) + newLeft = currLeft + _kMTransX * _kMScaleX; + newTop = currTop + _kMTransY * _kMScaleY; + newRight = currRight * _kMScaleX; newBottom = currBottom * _kMScaleY; - //更新当前flutter节点currNode的相对坐标 -> 屏幕绝对坐标 + // 更新当前flutter节点currNode的相对坐标 -> 屏幕绝对坐标 SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); } else { - //若当前节点的相对坐标与父亲节点的相对坐标值相同,则直接继承坐标值 - if(currRight == parentRight && currBottom == parentBottom) { - newLeft = realParentLeft; - newTop = realParentTop; - newRight = realParentRight; + // 若当前节点的相对坐标与父亲节点的相对坐标值相同,则直接继承坐标值 + if (currRight == parentRight && currBottom == parentBottom) { + newLeft = realParentLeft; + newTop = realParentTop; + newRight = realParentRight; newBottom = realParentBottom; } else { // 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 - newLeft = (currLeft + _kMTransX) * realScaleFactor; - newTop = (currTop + _kMTransY) * realScaleFactor; - newRight = (currLeft + _kMTransX + currRight) * realScaleFactor; + newLeft = (currLeft + _kMTransX) * realScaleFactor; + newTop = (currTop + _kMTransY) * realScaleFactor; + newRight = (currLeft + _kMTransX + currRight) * realScaleFactor; newBottom = (currTop + _kMTransY + currBottom) * realScaleFactor; } SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); } - FML_DLOG(INFO) << "ConvertChildRelativeRectToSceenRect -> { nodeId: "< { nodeId: " + << currNode.id << ", (" << newLeft << ", " << newTop << ", " + << newRight << ", " << newBottom << ")}"; } /** - * 在flutter引擎里实现对特定id的elementinfo的节点属性配置 + * 实现对特定id的flutter节点到arkui的elementinfo节点转化 */ -void OhosAccessibilityBridge::FlutterNodeToElementInfoById(ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId) { - if(elementInfoFromList == nullptr) { +void OhosAccessibilityBridge::FlutterNodeToElementInfoById( + ArkUI_AccessibilityElementInfo* elementInfoFromList, + int64_t elementId) { + if (elementInfoFromList == nullptr) { FML_DLOG(INFO) << "OhosAccessibilityBridge::FlutterNodeToElementInfoById " "elementInfoFromList is null"; return; } - FML_DLOG(INFO) << "FlutterNodeToElementInfoById elementInfoFromList= "<(0)); + if (elementId == 0 || elementId == -1) { + // 获取flutter的root节点 + flutter::SemanticsNode flutterNode = + getOrCreateFlutterSemanticsNode(static_cast(0)); - //设置elementinfo的屏幕坐标范围 + // 设置elementinfo的屏幕坐标范围 int32_t left = static_cast(flutterNode.rect.fLeft); - int32_t top = static_cast(flutterNode.rect.fTop); + int32_t top = static_cast(flutterNode.rect.fTop); int32_t right = static_cast(flutterNode.rect.fRight); - int32_t bottom = static_cast(flutterNode.rect.fBottom); - ArkUI_AccessibleRect rect = {left, top, right, bottom}; //debug + int32_t bottom = static_cast(flutterNode.rect.fBottom); + ArkUI_AccessibleRect rect = {left, top, right, bottom}; // debug OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect); - //设置elementinfo的action类型 + // 设置elementinfo的action类型 int32_t actionTypeNum = 2; ArkUI_AccessibleAction actions[actionTypeNum]; - actions[0].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; + actions[0].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; actions[0].description = "获取焦点动作事件"; - actions[1].actionType = ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; actions[1].description = "清空焦点动作事件"; - OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions); + OH_ArkUI_AccessibilityElementInfoSetOperationActions( + elementInfoFromList, actionTypeNum, actions); - //根据flutternode信息配置对应的elementinfo - OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, 0); + // 根据flutternode信息配置对应的elementinfo + OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, 0); // NOTE: 系统强制设置root的父节点id = -2100000 - OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, -2100000); - //设置无障碍播报文本 - OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfoFromList, flutterNode.label.empty()? "root" : flutterNode.label.c_str()); // debug - OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes"); - OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, false); - - //配置child节点信息 - int32_t childCount = static_cast(flutterNode.childrenInTraversalOrder.size()); + OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, -2100000); + // 设置无障碍播报文本 + OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( + elementInfoFromList, flutterNode.label.empty() + ? "root" + : flutterNode.label.c_str()); // debug + OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, + "yes"); + OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, + false); + + // 配置child节点信息 + int32_t childCount = + static_cast(flutterNode.childrenInTraversalOrder.size()); int64_t childNodeIds[childCount]; - for(int32_t i=0; i(flutterNode.childrenInTraversalOrder[i]); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> elementid=0 childCount="< elementid=0 childCount=" + << childCount << " childNodeIds=" << childNodeIds[i]; } - OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds); + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, + childCount, childNodeIds); // 配置常用属性 OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true); @@ -321,120 +368,196 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById(ArkUI_AccessibilityEl OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); - OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root"); // debug - OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, "root_content"); + OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, + "root"); // debug + OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, + "root_content"); return; } - /** ----------------------------------------------- NOTE: when elementId >= 1 -------------------------------------------- */ - //根据elementid获取对应的flutter节点 - FML_DLOG(INFO) << "FlutterNodeToElementInfoById elementId = "<(elementId)); + /** NOTE: when elementId >= 1 */ + FML_DLOG(INFO) << "FlutterNodeToElementInfoById elementId = " << elementId; + flutter::SemanticsNode flutterNode = + getOrCreateFlutterSemanticsNode(static_cast(elementId)); + //获取当前节点的组件类型 + std::string componentTypeName = GetNodeComponentType(flutterNode); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById componentTypeName = " << componentTypeName; - // NOTE: 语义组件的父子节点相对坐标位置的矩阵变换,转化为绝对屏幕坐标 + //flutter父子节点相对坐标位置的矩阵变换,转化为绝对屏幕坐标 ConvertChildRelativeRectToSceenRect(flutterNode); auto rectPairs = GetAbsoluteScreenRect(flutterNode.id); - //设置elementinfo的屏幕坐标范围 + //设置elementinfo的屏幕绝对坐标rect int32_t left = rectPairs.first.first; - int32_t top = rectPairs.first.second; + int32_t top = rectPairs.first.second; int32_t right = rectPairs.second.first; - int32_t bottom = rectPairs.second.second; - ArkUI_AccessibleRect rect = {left, top, right, bottom}; + int32_t bottom = rectPairs.second.second; + ArkUI_AccessibleRect rect = {left, top, right, bottom}; OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> node.id= "< node.id= " + << flutterNode.id << " SceenRect = (" << left << ", " << top + << ", " << right << ", " << bottom << ")"; + + //若为非文本类输入框组件 + if(!flutterNode.HasFlag(FLAGS_::kIsTextField)) { + // 设置elementinfo的action类型 + int32_t actionTypeNum = 5; + ArkUI_AccessibleAction actions[actionTypeNum]; + actions[0].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; + actions[0].description = "获取焦点"; + actions[1].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].description = "清除焦点"; + actions[2].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; + actions[2].description = "点击动作"; + actions[3].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD; + actions[3].description = "向上滑动"; + actions[4].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD; + actions[4].description = "向下滑动"; + OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, + actionTypeNum, actions); + + } else { //若为textfield文本输入框组件类型 + // 设置elementinfo的action类型 + int32_t actionTypeNum = 12; + ArkUI_AccessibleAction actions[actionTypeNum]; + actions[0].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; + actions[0].description = "获取焦点"; + actions[1].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].description = "清除焦点"; + actions[2].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; + actions[2].description = "点击操作"; + actions[3].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD; + actions[3].description = "向上滑动"; + actions[4].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD; + actions[4].description = "向下滑动"; + actions[5].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK; + actions[5].description = "长按操作"; + actions[6].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY; + actions[6].description = "文本复制"; + actions[7].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE; + actions[7].description = "文本粘贴"; + actions[8].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT; + actions[8].description = "文本剪切"; + actions[9].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT; + actions[9].description = "文本选择"; + actions[10].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT; + actions[10].description = "文本内容设置"; + actions[11].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION; + actions[11].description = "光标位置设置"; + OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, + actionTypeNum, actions); + } + + // 根据flutternode信息配置对应的elementinfo + OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, + flutterNode.id); + + // 设置父节点id int32_t parentId = GetParentId(elementId); - if(parentId < 0) { - FML_DLOG(ERROR) << "FlutterNodeToElementInfoById GetParentId is null, assigned to "< elementid="< elementid=" << elementId + << " childCount=" << childCount + << " childNodeIds=" << childNodeIds[i]; } - OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds); + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, + childCount, childNodeIds); // 配置常用属性 + if(IsNodeFocusable(flutterNode)) { + OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true); + } OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true); - OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true); - // if(elementId == 4) { - // OH_ArkUI_AccessibilityElementInfoSetFocused(elementInfoFromList, true); - // } OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true); - // OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetSelected(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true); - //FIXME: 元素所属的组件类型(如:root, button,text等) - std::string componentTypeName = GetNodeComponentType(flutterNode); - if(elementId == 0) { - OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root"); + // FIXME: 元素所属的组件类型(如:root, button,text等) + if (elementId == 0) { + OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, + "root"); } else { - OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, componentTypeName.c_str()); + OH_ArkUI_AccessibilityElementInfoSetComponentType( + elementInfoFromList, componentTypeName.c_str()); } - FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetComponentType: "< arkui语义节点树 - // FlutterTreeToArkuiTree(elementList); - - if(mode == ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { - /** Search for current nodes. (mode = 0) */ - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - int64_t elementInfoCount = static_cast(flutterSemanticsTree_.size()); - for(int64_t i=1; i arkui语义节点树 + // FlutterTreeToArkuiTree(elementList); + + if (mode == ArkUI_AccessibilitySearchMode:: + ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { + /** Search for current nodes. (mode = 0) */ + FlutterNodeToElementInfoById(elementInfoFromList, elementId); + int64_t elementInfoCount = + static_cast(flutterSemanticsTree_.size()); + for (int64_t i = 1; i < elementInfoCount; i++) { + ArkUI_AccessibilityElementInfo* newElementInfo = + OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + FlutterNodeToElementInfoById(newElementInfo, i); + } - } else if(mode == ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS) { - /** Search for parent nodes. (mode = 1) */ - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - // int64_t elementInfoCount = static_cast(flutterSemanticsTree_.size()); - // for(int64_t i=1; i(flutterSemanticsTree_.size()); - // for(int64_t i=1; i(flutterSemanticsTree_.size()); - // for(int64_t i=1; i(flutterSemanticsTree_.size()); - for(int64_t i=1; i(flutterSemanticsTree_.size()); for(int64_t i=1; + // i(flutterSemanticsTree_.size()); for(int64_t i=1; + // i(flutterSemanticsTree_.size()); for(int64_t i=1; + // i(flutterSemanticsTree_.size()); + for (int64_t i = 1; i < elementInfoCount; i++) { + ArkUI_AccessibilityElementInfo* newElementInfo = + OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + FlutterNodeToElementInfoById(newElementInfo, i); + } } else { - FlutterNodeToElementInfoById(elementInfoFromList, elementId); + FlutterNodeToElementInfoById(elementInfoFromList, elementId); } FML_DLOG(INFO) << "--- FindAccessibilityNodeInfosById is end ---"; @@ -512,8 +657,8 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosByText( const char* text, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { - //TODO - FML_DLOG(INFO)<<"=== FindAccessibilityNodeInfosByText is end"; + // TODO + FML_DLOG(INFO) << "=== FindAccessibilityNodeInfosByText is end"; return 0; } int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( @@ -521,8 +666,8 @@ int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( ArkUI_AccessibilityFocusType focusType, int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo) { - //TODO - FML_DLOG(INFO)<<"=== FindFocusedAccessibilityNode is end"; + // TODO + FML_DLOG(INFO) << "=== FindFocusedAccessibilityNode is end"; return 0; } @@ -531,149 +676,186 @@ int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( ArkUI_AccessibilityFocusMoveDirection direction, int32_t requestId, ArkUI_AccessibilityElementInfo* elementList) { - //TODO - FML_DLOG(INFO)<<"=== FindNextFocusAccessibilityNode is end"; + // TODO + FML_DLOG(INFO) << "=== FindNextFocusAccessibilityNode is end"; return 0; } /** 将arkui的action类型转化为flutter的action类型 */ int32_t ActionTypeConversion(ArkUI_Accessibility_ActionType arkui_action) { - //部分arkui操作和flutter操作的映射,其余action暂时无法适配, 这里先return 0 - switch(arkui_action) { - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: + // 部分arkui操作和flutter操作的映射,其余action暂时无法适配, 这里先return 0 + switch (arkui_action) { + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: return static_cast(ACTIONS_::kTap); - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: return static_cast(ACTIONS_::kLongPress); - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: return static_cast(ACTIONS_::kScrollUp); - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: return static_cast(ACTIONS_::kScrollDown); - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: return static_cast(ACTIONS_::kCopy); - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: return static_cast(ACTIONS_::kCut); - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: return static_cast(ACTIONS_::kDidGainAccessibilityFocus); - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: return static_cast(ACTIONS_::kDidLoseAccessibilityFocus); - //Text selection action, requiring the setting of selectTextBegin, TextEnd, and TextInForward - //parameters to select a text segment in the text box. */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: + // Text selection action, requiring the setting of selectTextBegin, + // TextEnd, and TextInForward parameters to select a text + // segment in the text box. */ + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: return static_cast(ACTIONS_::kSetSelection); - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: return static_cast(ACTIONS_::kSetText); - default: - return static_cast(ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID); + default: + return static_cast( + ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID); } } -void DispatchSemanticsAction(int32_t id, flutter::SemanticsAction action ) { - FML_DLOG(INFO)<<"DispatchSemanticsAction is called"; - //TODO: ... 发送语义动作解析 - // SHELL_HOLDER->GetPlatformView()->DispatchSemanticsAction(id, action, {}); +void DispatchSemanticsAction(int32_t id, flutter::SemanticsAction action) { + FML_DLOG(INFO) << "DispatchSemanticsAction is called"; + // TODO: ... 发送语义动作解析 + // SHELL_HOLDER->GetPlatformView()->DispatchSemanticsAction(id, action, {}); } /** - * TODO: 执行语义动作解析,当FindAccessibilityNodeInfosById找到相应的elementinfo时才会触发该回调函数 + * TODO: + * 执行语义动作解析,当FindAccessibilityNodeInfosById找到相应的elementinfo时才会触发该回调函数 */ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( int64_t elementId, ArkUI_Accessibility_ActionType action, - ArkUI_AccessibilityActionArguments *actionArguments, + ArkUI_AccessibilityActionArguments* actionArguments, int32_t requestId) { - - FML_DLOG(INFO)<<"ExecuteAccessibilityAction input-params-> elementId="< elementId=" + << elementId << " action=" << action + << " requestId=" << requestId + << " *actionArguments=" << actionArguments; + + if (actionArguments == nullptr) { + FML_DLOG(ERROR) << "OhosAccessibilityBridge::ExecuteAccessibilityAction " + "actionArguments = null"; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } // std::string key = ""; // char* value; - // int32_t ret = OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key.c_str(), &value); - // if(value == nullptr) { - // FML_DLOG(ERROR)<<"ExecuteAccessibilityAction OH_ArkUI_FindAccessibilityActionArgumentByKey value = null"; - // return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; - // } - // if(ret == ArkUI_AcessbilityErrorCode::ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER) { - // FML_DLOG(ERROR)<<"ExecuteAccessibilityAction OH_ArkUI_FindAccessibilityActionArgumentByKey BAD_PARAMETER"; - // } else if(ret == ArkUI_AcessbilityErrorCode::ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED) { - // FML_DLOG(ERROR)<<"ExecuteAccessibilityAction OH_ArkUI_FindAccessibilityActionArgumentByKey RESULT_FAILED"; + // int32_t ret = + // OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key.c_str(), + // &value); if(value == nullptr) { + // FML_DLOG(ERROR)<<"ExecuteAccessibilityAction + // OH_ArkUI_FindAccessibilityActionArgumentByKey value = null"; return + // ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; + // } + // if(ret == + // ArkUI_AcessbilityErrorCode::ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER) + // { + // FML_DLOG(ERROR)<<"ExecuteAccessibilityAction + // OH_ArkUI_FindAccessibilityActionArgumentByKey BAD_PARAMETER"; + // } else if(ret == + // ArkUI_AcessbilityErrorCode::ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED) { + // FML_DLOG(ERROR)<<"ExecuteAccessibilityAction + // OH_ArkUI_FindAccessibilityActionArgumentByKey RESULT_FAILED"; // } else { - // FML_DLOG(INFO)<<"ExecuteAccessibilityAction OH_ArkUI_FindAccessibilityActionArgumentByKey RESULT_SUCCESSFUL"; + // FML_DLOG(INFO)<<"ExecuteAccessibilityAction + // OH_ArkUI_FindAccessibilityActionArgumentByKey RESULT_SUCCESSFUL"; // } - //根据当前elementid和无障碍动作类型,发送无障碍事件 - ArkUI_AccessibilityEventType eventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; - Flutter_SendAccessibilityAsyncEvent(elementId, eventType); + // 根据当前elementid和无障碍动作类型,发送无障碍事件 + ArkUI_AccessibilityEventType eventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; + Flutter_SendAccessibilityAsyncEvent(elementId, eventType); - FML_DLOG(INFO)<<"OhosAccessibilityBridge::ExecuteAccessibilityAction is end"; + FML_DLOG(INFO) + << "OhosAccessibilityBridge::ExecuteAccessibilityAction is end"; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; } int32_t OhosAccessibilityBridge::ClearFocusedFocusAccessibilityNode() { - //todo ... - FML_DLOG(INFO)<<"=== ClearFocusedFocusAccessibilityNode is end"; + // todo ... + FML_DLOG(INFO) << "=== ClearFocusedFocusAccessibilityNode is end"; return 0; } -int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition(int64_t elementId, - int32_t requestId, - int32_t* index) { - //todo ... - FML_DLOG(INFO)<<"=== GetAccessibilityNodeCursorPosition is end"; +int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( + int64_t elementId, + int32_t requestId, + int32_t* index) { + // todo ... + FML_DLOG(INFO) << "=== GetAccessibilityNodeCursorPosition is end"; return 0; } /** * 自定义无障碍异步事件发送 */ -void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent(int64_t elementId, ArkUI_AccessibilityEventType eventType) { - //1.创建eventInfo对象 - ArkUI_AccessibilityEventInfo *eventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); - if(eventInfo == nullptr) { - FML_DLOG(ERROR)<<"Flutter_SendAccessibilityAsyncEvent OH_ArkUI_CreateAccessibilityEventInfo eventInfo = null"; +void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( + int64_t elementId, + ArkUI_AccessibilityEventType eventType) { + // 1.创建eventInfo对象 + ArkUI_AccessibilityEventInfo* eventInfo = + OH_ArkUI_CreateAccessibilityEventInfo(); + if (eventInfo == nullptr) { + FML_DLOG(ERROR) << "Flutter_SendAccessibilityAsyncEvent " + "OH_ArkUI_CreateAccessibilityEventInfo eventInfo = null"; return; } - - //2.创建的elementinfo并根据对应id的flutternode进行属性初始化 - ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); + // 2.创建的elementinfo并根据对应id的flutternode进行属性初始化 + ArkUI_AccessibilityElementInfo* _elementInfo = + OH_ArkUI_CreateAccessibilityElementInfo(); FlutterNodeToElementInfoById(_elementInfo, elementId); - OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused(_elementInfo, true); //debug + OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused(_elementInfo, + true); - //3.设置发送事件,如配置获焦事件 + // 3.设置发送事件,如配置获焦事件 OH_ArkUI_AccessibilityEventSetEventType(eventInfo, eventType); - //4.将eventinfo事件和当前elementinfo进行绑定 + // 4.将eventinfo事件和当前elementinfo进行绑定 OH_ArkUI_AccessibilityEventSetElementInfo(eventInfo, _elementInfo); - //5.调用接口发送到ohos侧 + // 5.调用接口发送到ohos侧 auto callback = [](int32_t errorCode) { - FML_DLOG(INFO)<<"Flutter_SendAccessibilityAsyncEvent callback-> errorCode ="< errorCode =" + << errorCode; }; - //6.发送event到OH侧 - if(provider_ == nullptr) { - FML_DLOG(ERROR)<<"Flutter_SendAccessibilityAsyncEvent AccessibilityProvider = nullptr"; + // 6.发送event到OH侧 + if (provider_ == nullptr) { + FML_DLOG(ERROR) << "Flutter_SendAccessibilityAsyncEvent " + "AccessibilityProvider = nullptr"; return; } OH_ArkUI_SendAccessibilityAsyncEvent(provider_, eventInfo, callback); - //7.销毁新创建的elementinfo + // 7.销毁新创建的elementinfo // OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); - FML_DLOG(INFO)<<"OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent is end"; + FML_DLOG(INFO) + << "OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent is end"; return; } @@ -682,7 +864,6 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent(int64_t elemen */ bool OhosAccessibilityBridge::IsNodeFocusable( const flutter::SemanticsNode& node) { - if (node.HasFlag(FLAGS_::kScopesRoute)) { return false; } @@ -707,9 +888,9 @@ bool OhosAccessibilityBridge::IsNodeFocusable( void OhosAccessibilityBridge::updateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { - FML_DLOG(INFO)<< ("OhosAccessibilityBridge::updateSemantics is called"); + FML_DLOG(INFO) << ("OhosAccessibilityBridge::updateSemantics is called"); - //每次flutter语义节点更新,需要清空语义树容器节点信息 + // 每次flutter语义节点更新,需要清空语义树容器节点信息 flutterSemanticsTree_.clear(); parentChildIdVec.clear(); @@ -771,17 +952,18 @@ void OhosAccessibilityBridge::updateSemantics( const flutter::SemanticsNode& node = item.second; printTest(node); // print node struct for debugging - //构建flutter无障碍语义节点树 + // 构建flutter无障碍语义节点树 flutterSemanticsTree_.insert({node.id, node}); if (node.HasFlag(FLAGS_::kIsHidden)) { // 判断当前更新节点是隐藏的 continue; } if (IsNodeFocusable(node)) { // 判断当前更新节点是否获焦 - FML_DLOG(INFO) <<"UpdateSemantics -> flutterNode is focusable, node.id="< flutterNode is focusable, node.id=" + << node.id; + // 将获焦语义节点加入到flutterSemanticsTree + // flutterSemanticsTree_.insert({node.id, node}); + // flutterSemanticsTreeVec.push_back(node); } // todo:根据nodeId获取当前os对应的真实节点 @@ -791,11 +973,14 @@ void OhosAccessibilityBridge::updateSemantics( // todo:获取当前节点的全部子节点数量,并构建当前节点的全部更新子节点 int32_t childNodeCount = node.childrenInTraversalOrder.size(); for (int32_t i = 0; i < childNodeCount; i++) { - parentChildIdVec.emplace_back(std::make_pair(node.id, node.childrenInTraversalOrder[i])); - FML_DLOG(INFO) <<"UpdateSemantics parentChildIdMap -> ("< (" << node.id + << ", " << node.childrenInTraversalOrder[i] << ")"; // todo:通过遍历当前节点的子节点,并对所有子节点进行逐一构建os对应的elementinfo - // AccessibilityElementInfo* child = createAccessibilityElementInfo(node.childrenInTraversalOrder[i]); + // AccessibilityElementInfo* child = + // createAccessibilityElementInfo(node.childrenInTraversalOrder[i]); // todo:将所有的新child节点加入到os对应的elementInfoList中 } // TODO: 将更新后的全部子节点赋值给当前真实节点 @@ -897,28 +1082,31 @@ void OhosAccessibilityBridge::updateSemantics( } } - for(const auto& item: flutterSemanticsTree_) { - FML_DLOG(INFO)<<"flutterSemanticsTree_ -> {"< {" << item.first << ", " + << item.second.id << "}"; } - for(const auto& item: parentChildIdVec) { - FML_DLOG(INFO)<<"parentChildIdVec -> ("< (" << item.first << ", " + << item.second << ")"; } } -/** 获取当前flutter节点的组件类型 */ +/** 获取当前flutter节点的组件类型,并映射为arkui组件 */ std::string OhosAccessibilityBridge::GetNodeComponentType( const flutter::SemanticsNode& node) { - - if((!node.label.empty() || !node.tooltip.empty() || !node.hint.empty()) && node.id != 0) { - return "text"; + if ((!node.label.empty() || !node.tooltip.empty() || !node.hint.empty()) && + node.id != 0) { + return "Text"; } if (node.HasFlag(FLAGS_::kIsButton)) { - return "button"; + return "Button"; } if (node.HasFlag(FLAGS_::kIsTextField)) { - return "TextField"; + //arkui没有textfield,这里直接透传 + return "TextInput"; } if (node.HasFlag(FLAGS_::kIsLink)) { @@ -941,7 +1129,7 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( if (node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup)) { return "RadioButton"; } else { - return "CheckBox"; + return "Checkbox"; } } @@ -954,26 +1142,29 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( // 获取根节点 flutter::SemanticsNode OhosAccessibilityBridge::getFlutterRootSemanticsNode() { - if(!flutterSemanticsTree_.size()) { - FML_DLOG(ERROR)<<"getFlutterRootSemanticsNode -> flutterSemanticsTree_.size()=0"; + if (!flutterSemanticsTree_.size()) { + FML_DLOG(ERROR) + << "getFlutterRootSemanticsNode -> flutterSemanticsTree_.size()=0"; return flutter::SemanticsNode{}; } - if(flutterSemanticsTree_.find(0) == flutterSemanticsTree_.end()) { - FML_DLOG(ERROR)<<"getFlutterRootSemanticsNode -> flutterSemanticsTree_ has no keys = 0"; - return flutter::SemanticsNode{}; + if (flutterSemanticsTree_.find(0) == flutterSemanticsTree_.end()) { + FML_DLOG(ERROR) << "getFlutterRootSemanticsNode -> flutterSemanticsTree_ " + "has no keys = 0"; + return flutter::SemanticsNode{}; } return flutterSemanticsTree_.at(0); } void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { - //todo ... + // todo ... } void OhosAccessibilityBridge::removeSemanticsNode( flutter::SemanticsNode nodeToBeRemoved) { - //todo ... - if(!flutterSemanticsTree_.size()) { - FML_DLOG(ERROR)<<"OhosAccessibilityBridge::removeSemanticsNode -> flutterSemanticsTree_.szie()=0"; + // todo ... + if (!flutterSemanticsTree_.size()) { + FML_DLOG(ERROR) << "OhosAccessibilityBridge::removeSemanticsNode -> " + "flutterSemanticsTree_.szie()=0"; return; } if (flutterSemanticsTree_.find(nodeToBeRemoved.id) == @@ -995,16 +1186,27 @@ void OhosAccessibilityBridge::printTest(flutter::SemanticsNode node) { FML_DLOG(INFO) << "node.id=" << node.id; FML_DLOG(INFO) << "node.flags=" << node.flags; FML_DLOG(INFO) << "node.actions=" << node.actions; - FML_DLOG(INFO) << "node.rect= {" << node.rect.fLeft<<", "< kMScaleX=" << _transform.get(SkMatrix::kMScaleX); - FML_DLOG(INFO) << "node.transform -> kMSkewX=" << _transform.get(SkMatrix::kMSkewX); - FML_DLOG(INFO) << "node.transform -> kMTransX=" << _transform.get(SkMatrix::kMTransX); - FML_DLOG(INFO) << "node.transform -> kMSkewY=" << _transform.get(SkMatrix::kMSkewY); - FML_DLOG(INFO) << "node.transform -> kMScaleY=" << _transform.get(SkMatrix::kMScaleY); - FML_DLOG(INFO) << "node.transform -> kMTransY=" << _transform.get(SkMatrix::kMTransY); - FML_DLOG(INFO) << "node.transform -> kMPersp0=" << _transform.get(SkMatrix::kMPersp0); - FML_DLOG(INFO) << "node.transform -> kMPersp1=" << _transform.get(SkMatrix::kMPersp1); - FML_DLOG(INFO) << "node.transform -> kMPersp2=" << _transform.get(SkMatrix::kMPersp2); + FML_DLOG(INFO) << "node.rect= {" << node.rect.fLeft << ", " << node.rect.fTop + << ", " << node.rect.fRight << ", " << node.rect.fBottom + << "}"; + FML_DLOG(INFO) << "node.transform -> kMScaleX=" + << _transform.get(SkMatrix::kMScaleX); + FML_DLOG(INFO) << "node.transform -> kMSkewX=" + << _transform.get(SkMatrix::kMSkewX); + FML_DLOG(INFO) << "node.transform -> kMTransX=" + << _transform.get(SkMatrix::kMTransX); + FML_DLOG(INFO) << "node.transform -> kMSkewY=" + << _transform.get(SkMatrix::kMSkewY); + FML_DLOG(INFO) << "node.transform -> kMScaleY=" + << _transform.get(SkMatrix::kMScaleY); + FML_DLOG(INFO) << "node.transform -> kMTransY=" + << _transform.get(SkMatrix::kMTransY); + FML_DLOG(INFO) << "node.transform -> kMPersp0=" + << _transform.get(SkMatrix::kMPersp0); + FML_DLOG(INFO) << "node.transform -> kMPersp1=" + << _transform.get(SkMatrix::kMPersp1); + FML_DLOG(INFO) << "node.transform -> kMPersp2=" + << _transform.get(SkMatrix::kMPersp2); FML_DLOG(INFO) << "node.maxValueLength=" << node.maxValueLength; FML_DLOG(INFO) << "node.currentValueLength=" << node.currentValueLength; FML_DLOG(INFO) << "node.textSelectionBase=" << node.textSelectionBase; -- Gitee From 9a5c3d47b73fb30cb6b129c66612ec5f04009a28 Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 18 Sep 2024 19:06:40 +0800 Subject: [PATCH 028/151] =?UTF-8?q?feat:=E4=BC=98=E5=8C=96flutter=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E9=80=8F=E4=BC=A0=E4=B8=BAarkui=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E7=9A=84=E9=80=BB=E8=BE=91,=E6=A0=BC=E5=BC=8F=E5=8C=96?= =?UTF-8?q?=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 230 ++++++++---------- 1 file changed, 100 insertions(+), 130 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index dde1a24db8..21a2f18d0a 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -239,18 +239,14 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( auto _kMTransX = transform.get(SkMatrix::kMTransX); auto _kMScaleY = transform.get(SkMatrix::kMScaleY); auto _kMTransY = transform.get(SkMatrix::kMTransY); - /** 以下矩阵坐标变换参数(如:旋转/错切、透视)场景目前暂不考虑 */ - // auto _kMSkewX = transform.get(SkMatrix::kMSkewX); - // auto _kMSkewY = transform.get(SkMatrix::kMSkewY); - // auto _kMPersp0 = transform.get(SkMatrix::kMPersp0); - // auto _kMPersp1 = transform.get(SkMatrix::kMPersp1); - // auto _kMPersp2 = transform.get(SkMatrix::kMPersp2); + /** 以下矩阵坐标变换参数(如:旋转/错切、透视)场景目前暂不考虑 + * NOTE: SkMatrix::kMSkewX, SkMatrix::kMSkewY, + * SkMatrix::kMPersp0, SkMatrix::kMPersp1, SkMatrix::kMPersp2 + */ // 获取当前flutter节点的父节点的相对rect int32_t parentId = GetParentId(currNode.id); auto parentNode = getOrCreateFlutterSemanticsNode(parentId); - // auto parentLeft = parentNode.rect.fLeft; - // auto parentTop = parentNode.rect.fTop; auto parentRight = parentNode.rect.fRight; auto parentBottom = parentNode.rect.fBottom; @@ -367,9 +363,8 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); - OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, - "root"); // debug + "root"); OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, "root_content"); @@ -594,39 +589,18 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS) { /** Search for parent nodes. (mode = 1) */ FlutterNodeToElementInfoById(elementInfoFromList, elementId); - // int64_t elementInfoCount = - // static_cast(flutterSemanticsTree_.size()); for(int64_t i=1; - // i(flutterSemanticsTree_.size()); for(int64_t i=1; - // i(flutterSemanticsTree_.size()); for(int64_t i=1; - // i visitedObjs; - // SEMANTICS_NODE_ rootObj = getRootSemanticsNode(); std::vector newRoutes; // 遍历更新的actions,并将所有的actions的id添加进actionMap @@ -947,44 +920,94 @@ void OhosAccessibilityBridge::updateSemantics( // } // } + /** + * 从dart层 -> c++层传递 + * NOTE: flutter语义树的更新过程,获取每个语义节点的更新属性 + */ for (auto& item : update) { // 获取当前更新的节点node const flutter::SemanticsNode& node = item.second; - printTest(node); // print node struct for debugging + printTest(node); // print node info for debugging // 构建flutter无障碍语义节点树 - flutterSemanticsTree_.insert({node.id, node}); + if(flutterSemanticsTree_.count(node.id) == 0) { + flutterSemanticsTree_.insert({node.id, node}); + } else { + FML_DLOG(ERROR) << "UpdateSemantics -> flutterSemanticsTree_: node.id=" + << node.id<<" has already exists !"; + } - if (node.HasFlag(FLAGS_::kIsHidden)) { // 判断当前更新节点是隐藏的 + // 若当前更新节点是隐藏的,则跳过 + if (node.HasFlag(FLAGS_::kIsHidden)) { continue; } - if (IsNodeFocusable(node)) { // 判断当前更新节点是否获焦 + // 判断flutter节点是否获焦 + if (IsNodeFocusable(node)) { FML_DLOG(INFO) << "UpdateSemantics -> flutterNode is focusable, node.id=" << node.id; - // 将获焦语义节点加入到flutterSemanticsTree - // flutterSemanticsTree_.insert({node.id, node}); - // flutterSemanticsTreeVec.push_back(node); } - // todo:根据nodeId获取当前os对应的真实节点 - // currentNode = - // ArkUI_AccessibilityElementInfo::createAccessibilityElementInfo(node.id); - - // todo:获取当前节点的全部子节点数量,并构建当前节点的全部更新子节点 + //获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 int32_t childNodeCount = node.childrenInTraversalOrder.size(); for (int32_t i = 0; i < childNodeCount; i++) { parentChildIdVec.emplace_back( std::make_pair(node.id, node.childrenInTraversalOrder[i])); FML_DLOG(INFO) << "UpdateSemantics parentChildIdMap -> (" << node.id << ", " << node.childrenInTraversalOrder[i] << ")"; - - // todo:通过遍历当前节点的子节点,并对所有子节点进行逐一构建os对应的elementinfo - // AccessibilityElementInfo* child = - // createAccessibilityElementInfo(node.childrenInTraversalOrder[i]); - // todo:将所有的新child节点加入到os对应的elementInfoList中 } - // TODO: 将更新后的全部子节点赋值给当前真实节点 - // currentNode = newChildren + + //TODO: 若该对象是输入焦点节点,且发生更新变化,则发送给os有关它的信息 + // std::shared_ptr + // inputFocusedSemanticsNode; // 当前输入焦点节点 + // std::shared_ptr + // lastInputFocusedSemanticsNode; // 上一个输入焦点节点 + // bool isHadFlag = true; + // if (inputFocusedSemanticsNode != nullptr && + // inputFocusedSemanticsNode->id == node.id && + // (lastInputFocusedSemanticsNode == nullptr || + // lastInputFocusedSemanticsNode->id != inputFocusedSemanticsNode->id)) { + // // 上次输入焦点节点 -> 当前输入焦点节点 + // lastInputFocusedSemanticsNode = inputFocusedSemanticsNode; + // // 发送相应的输入焦点改变事件 + // // sendAccessibilityEvent(obtainAccessibilityEvent(object.id, + // // AccessibilityEvent.TYPE_VIEW_FOCUSED)); + // } else if (inputFocusedSemanticsNode == nullptr) { + // // There's no TYPE_VIEW_CLEAR_FOCUSED event, so if the current input focus + // // becomes null, then we just set the last one to null too, so that it + // // sends the event again when something regains focus. + // lastInputFocusedSemanticsNode = nullptr; + // } + + // if (inputFocusedSemanticsNode != nullptr && + // inputFocusedSemanticsNode->id == node.id && isHadFlag && + // node.HasFlag(FLAGS_::kIsTextField) + // // If we have a TextField that has InputFocus, we should avoid + // // announcing it if something else we track has a11y focus. This needs + // // to still work when, e.g., IME has a11y focus or the "PASTE" popup is + // // used though. See more discussion at + // // https://github.com/flutter/flutter/issues/23180 + // && (accessibilityFocusedSemanticsNode == nullptr || + // (accessibilityFocusedSemanticsNode->id == + // inputFocusedSemanticsNode->id))) { + // // 这里写输入框更新文字内容,将老旧的文本替换为新输入文字,并发送textchange事件 + // // AccessibilityEvent event = createTextChangedEvent(object.id, oldValue, + // // newValue); sendAccessibilityEvent(event); + + // // todo:若当前textselection部分和之前的textselection部分不同,则触发 + // int32_t previousTextSelectionBase = 0; + // int32_t previousTextSelectionExtent = 1; + // if (previousTextSelectionBase != node.textSelectionBase || + // previousTextSelectionExtent != node.textSelectionExtent) { + // // 创建并发送textselection改变事件 + // // AccessibilityEvent selectionEvent = obtainAccessibilityEvent( + // // object.id, AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); + // // selectionEvent.getText().add(newValue); + // // selectionEvent.setFromIndex(object.textSelectionBase); + // // selectionEvent.setToIndex(object.textSelectionExtent); + // // selectionEvent.setItemCount(newValue.length()); + // // sendAccessibilityEvent(selectionEvent); + // } + // } // todo: 是否触发滑动操作 bool didScroll = true; @@ -1011,77 +1034,13 @@ void OhosAccessibilityBridge::updateSemantics( } // sendAccessibilityEvent(event) } - // todo: 判断是否触发liveRegion活动区,是否活跃 - if (node.HasFlag(FLAGS_::kIsLiveRegion)) { - // sendWindowContentChangeEvent(object.id); - } - - // todo:当前焦点语义节点 - bool isHadFlag = false; // 这里判断previousFlag和当前flag是否相同 - std::shared_ptr accessibilityFocusedSemanticsNode; - if (accessibilityFocusedSemanticsNode != nullptr && - accessibilityFocusedSemanticsNode->id == node.id && !isHadFlag && - node.HasFlag(FLAGS_::kIsSelected)) { - // todo:创建并发送事件 - // AccessibilityEvent event = obtainAccessibilityEvent( - // node.id, AccessibilityEvent.TYPE_VIEW_SELECTED); - // event.getText().add(object.label); - // sendAccessibilityEvent(event); - } - // todo: 若该对象是输入焦点节点,且发生更新变化,则发送给os有关它的信息 - std::shared_ptr - inputFocusedSemanticsNode; // 当前输入焦点节点 - std::shared_ptr - lastInputFocusedSemanticsNode; // 上一个输入焦点节点 - if (inputFocusedSemanticsNode != nullptr && - inputFocusedSemanticsNode->id == node.id && - (lastInputFocusedSemanticsNode == nullptr || - lastInputFocusedSemanticsNode->id != inputFocusedSemanticsNode->id)) { - // 上次输入焦点节点 -> 当前输入焦点节点 - lastInputFocusedSemanticsNode = inputFocusedSemanticsNode; - // 发送相应的输入焦点改变事件 - // sendAccessibilityEvent(obtainAccessibilityEvent(object.id, - // AccessibilityEvent.TYPE_VIEW_FOCUSED)); - } else if (inputFocusedSemanticsNode == nullptr) { - // There's no TYPE_VIEW_CLEAR_FOCUSED event, so if the current input focus - // becomes null, then we just set the last one to null too, so that it - // sends the event again when something regains focus. - lastInputFocusedSemanticsNode = nullptr; - } - - if (inputFocusedSemanticsNode != nullptr && - inputFocusedSemanticsNode->id == node.id && isHadFlag && - node.HasFlag(FLAGS_::kIsTextField) - // If we have a TextField that has InputFocus, we should avoid - // announcing it if something else we track has a11y focus. This needs - // to still work when, e.g., IME has a11y focus or the "PASTE" popup is - // used though. See more discussion at - // https://github.com/flutter/flutter/issues/23180 - && (accessibilityFocusedSemanticsNode == nullptr || - (accessibilityFocusedSemanticsNode->id == - inputFocusedSemanticsNode->id))) { - // 这里写输入框更新文字内容,将老旧的文本替换为新输入文字,并发送textchange事件 - // AccessibilityEvent event = createTextChangedEvent(object.id, oldValue, - // newValue); sendAccessibilityEvent(event); - - // todo:若当前textselection部分和之前的textselection部分不同,则触发 - int32_t previousTextSelectionBase = 0; - int32_t previousTextSelectionExtent = 1; - if (previousTextSelectionBase != node.textSelectionBase || - previousTextSelectionExtent != node.textSelectionExtent) { - // 创建并发送textselection改变事件 - // AccessibilityEvent selectionEvent = obtainAccessibilityEvent( - // object.id, AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); - // selectionEvent.getText().add(newValue); - // selectionEvent.setFromIndex(object.textSelectionBase); - // selectionEvent.setToIndex(object.textSelectionExtent); - // selectionEvent.setItemCount(newValue.length()); - // sendAccessibilityEvent(selectionEvent); - } + // 判断是否触发liveRegion活动区,当前节点是否活跃(优先级低) + if (node.HasFlag(FLAGS_::kIsLiveRegion)) { + // TODO: ... } - } + //打印flutter语义树的不同节点的属性信息 for (const auto& item : flutterSemanticsTree_) { FML_DLOG(INFO) << "flutterSemanticsTree_ -> {" << item.first << ", " << item.second.id << "}"; @@ -1090,15 +1049,12 @@ void OhosAccessibilityBridge::updateSemantics( FML_DLOG(INFO) << "parentChildIdVec -> (" << item.first << ", " << item.second << ")"; } + } } /** 获取当前flutter节点的组件类型,并映射为arkui组件 */ std::string OhosAccessibilityBridge::GetNodeComponentType( const flutter::SemanticsNode& node) { - if ((!node.label.empty() || !node.tooltip.empty() || !node.hint.empty()) && - node.id != 0) { - return "Text"; - } if (node.HasFlag(FLAGS_::kIsButton)) { return "Button"; @@ -1109,6 +1065,11 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( return "TextInput"; } + if(node.HasFlag(FLAGS_::kIsMultiline)) { + //arkui没有多行文本textfield,这里直接透传 + return "TextArea"; + } + if (node.HasFlag(FLAGS_::kIsLink)) { return "Link"; } @@ -1121,20 +1082,28 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( if (node.HasFlag(FLAGS_::kIsHeader)) { return "Header"; } + if (node.HasFlag(FLAGS_::kIsImage)) { return "Image"; } if (node.HasFlag(FLAGS_::kHasCheckedState)) { if (node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup)) { - return "RadioButton"; + //arkui没有RadioButton,这里透传为Radio + return "Radio"; } else { return "Checkbox"; } } if (node.HasFlag(FLAGS_::kHasToggledState)) { - return "ToggleSwitch"; + //arkui没有ToggleSwitch,这里透传为Toggle + return "Toggle"; + } + + if ((!node.label.empty() || !node.tooltip.empty() || (!node.hint.empty()) && + node.id != 0)) { + return "Text"; } return "Widget" + std::to_string(node.id); @@ -1171,11 +1140,12 @@ void OhosAccessibilityBridge::removeSemanticsNode( flutterSemanticsTree_.end()) { FML_DLOG(INFO) << "Attempted to remove a node that is not in the tree."; } - // if (flutterSemanticsTree_.at(nodeToBeRemoved.id) != nodeToBeRemoved) { - // FML_DLOG(ERROR) << "Flutter semantics tree failed to get expected node " - // "when searching by id."; - // } - // nodeToBeRemoved.parent = nullptr; + int32_t nodeToBeRemovedParentId = GetParentId(nodeToBeRemoved.id); + for(auto it=parentChildIdVec.begin(); it!=parentChildIdVec.end(); it++) { + if(it->first == nodeToBeRemovedParentId && it->second == nodeToBeRemoved.id) { + parentChildIdVec.erase(it); + } + } if (nodeToBeRemoved.platformViewId != -1) { } } -- Gitee From 7f31beed418d038f13a7402f5d239687f47b238c Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 19 Sep 2024 15:35:38 +0800 Subject: [PATCH 029/151] =?UTF-8?q?feat:=E5=AE=8C=E5=96=84executeAccessibi?= =?UTF-8?q?lityAction=E6=96=B9=E6=B3=95=E7=9A=84=E5=B1=8F=E5=B9=95?= =?UTF-8?q?=E5=8A=A8=E4=BD=9C=E8=A7=A3=E6=9E=90=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E4=BC=A0=E9=80=92=E7=9B=B8=E5=BA=94=E7=9A=84=E5=8A=A8?= =?UTF-8?q?=E4=BD=9C=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 288 +++++++++++------- 1 file changed, 180 insertions(+), 108 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 21a2f18d0a..3b02ab1f1b 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -157,7 +157,8 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( // 设置组件类型 std::string componentTypeName = GetNodeComponentType(flutterNode); - OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfo, componentTypeName.c_str()); + OH_ArkUI_AccessibilityElementInfoSetComponentType( + elementInfo, componentTypeName.c_str()); std::string contents = componentTypeName + "_content"; OH_ArkUI_AccessibilityElementInfoSetContents(elementInfo, contents.c_str()); @@ -239,10 +240,10 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( auto _kMTransX = transform.get(SkMatrix::kMTransX); auto _kMScaleY = transform.get(SkMatrix::kMScaleY); auto _kMTransY = transform.get(SkMatrix::kMTransY); - /** 以下矩阵坐标变换参数(如:旋转/错切、透视)场景目前暂不考虑 - * NOTE: SkMatrix::kMSkewX, SkMatrix::kMSkewY, + /** 以下矩阵坐标变换参数(如:旋转/错切、透视)场景目前暂不考虑 + * NOTE: SkMatrix::kMSkewX, SkMatrix::kMSkewY, * SkMatrix::kMPersp0, SkMatrix::kMPersp1, SkMatrix::kMPersp2 - */ + */ // 获取当前flutter节点的父节点的相对rect int32_t parentId = GetParentId(currNode.id); @@ -375,14 +376,15 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( FML_DLOG(INFO) << "FlutterNodeToElementInfoById elementId = " << elementId; flutter::SemanticsNode flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); - //获取当前节点的组件类型 + // 获取当前节点的组件类型 std::string componentTypeName = GetNodeComponentType(flutterNode); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById componentTypeName = " << componentTypeName; + FML_DLOG(INFO) << "FlutterNodeToElementInfoById componentTypeName = " + << componentTypeName; - //flutter父子节点相对坐标位置的矩阵变换,转化为绝对屏幕坐标 + // flutter父子节点相对坐标位置的矩阵变换,转化为绝对屏幕坐标 ConvertChildRelativeRectToSceenRect(flutterNode); auto rectPairs = GetAbsoluteScreenRect(flutterNode.id); - //设置elementinfo的屏幕绝对坐标rect + // 设置elementinfo的屏幕绝对坐标rect int32_t left = rectPairs.first.first; int32_t top = rectPairs.first.second; int32_t right = rectPairs.second.first; @@ -393,8 +395,8 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( << flutterNode.id << " SceenRect = (" << left << ", " << top << ", " << right << ", " << bottom << ")"; - //若为非文本类输入框组件 - if(!flutterNode.HasFlag(FLAGS_::kIsTextField)) { + // 若为非文本类输入框组件 + if (!flutterNode.HasFlag(FLAGS_::kIsTextField)) { // 设置elementinfo的action类型 int32_t actionTypeNum = 5; ArkUI_AccessibleAction actions[actionTypeNum]; @@ -413,10 +415,10 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( actions[4].actionType = ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD; actions[4].description = "向下滑动"; - OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, - actionTypeNum, actions); + OH_ArkUI_AccessibilityElementInfoSetOperationActions( + elementInfoFromList, actionTypeNum, actions); - } else { //若为textfield文本输入框组件类型 + } else { // 若为textfield文本输入框组件类型 // 设置elementinfo的action类型 int32_t actionTypeNum = 12; ArkUI_AccessibleAction actions[actionTypeNum]; @@ -456,8 +458,8 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( actions[11].actionType = ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION; actions[11].description = "光标位置设置"; - OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, - actionTypeNum, actions); + OH_ArkUI_AccessibilityElementInfoSetOperationActions( + elementInfoFromList, actionTypeNum, actions); } // 根据flutternode信息配置对应的elementinfo @@ -500,7 +502,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( childCount, childNodeIds); // 配置常用属性 - if(IsNodeFocusable(flutterNode)) { + if (IsNodeFocusable(flutterNode)) { OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true); } OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); @@ -527,10 +529,10 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( // “no-hide-descendants”:当前组件及其所有子组件不可被无障碍辅助服务所识别。 // 默认值:“auto” OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, - "yes"); + "yes"); // 无障碍组,设置为true时表示该组件及其所有子组件为一整个可以选中的组件,无障碍服务将不再关注其子组件内容。默认值:false OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, - false); + false); FML_DLOG(INFO) << "OhosAccessibilityBridge::FlutterNodeToElementInfoById is end"; } @@ -632,7 +634,7 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosByText( int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { // TODO - FML_DLOG(INFO) << "=== FindAccessibilityNodeInfosByText is end"; + FML_DLOG(INFO) << "=== FindAccessibilityNodeInfosByText is end ==="; return 0; } int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( @@ -641,7 +643,7 @@ int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo) { // TODO - FML_DLOG(INFO) << "=== FindFocusedAccessibilityNode is end"; + FML_DLOG(INFO) << "=== FindFocusedAccessibilityNode is end ==="; return 0; } @@ -651,7 +653,7 @@ int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( int32_t requestId, ArkUI_AccessibilityElementInfo* elementList) { // TODO - FML_DLOG(INFO) << "=== FindNextFocusAccessibilityNode is end"; + FML_DLOG(INFO) << "=== FindNextFocusAccessibilityNode is end ==="; return 0; } @@ -716,7 +718,6 @@ void DispatchSemanticsAction(int32_t id, flutter::SemanticsAction action) { } /** - * TODO: * 执行语义动作解析,当FindAccessibilityNodeInfosById找到相应的elementinfo时才会触发该回调函数 */ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( @@ -735,36 +736,101 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } - // std::string key = ""; - // char* value; - // int32_t ret = - // OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key.c_str(), - // &value); if(value == nullptr) { - // FML_DLOG(ERROR)<<"ExecuteAccessibilityAction - // OH_ArkUI_FindAccessibilityActionArgumentByKey value = null"; return - // ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; - // } - // if(ret == - // ArkUI_AcessbilityErrorCode::ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER) - // { - // FML_DLOG(ERROR)<<"ExecuteAccessibilityAction - // OH_ArkUI_FindAccessibilityActionArgumentByKey BAD_PARAMETER"; - // } else if(ret == - // ArkUI_AcessbilityErrorCode::ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED) { - // FML_DLOG(ERROR)<<"ExecuteAccessibilityAction - // OH_ArkUI_FindAccessibilityActionArgumentByKey RESULT_FAILED"; - // } else { - // FML_DLOG(INFO)<<"ExecuteAccessibilityAction - // OH_ArkUI_FindAccessibilityActionArgumentByKey RESULT_SUCCESSFUL"; - // } + // NOTE: OH_ArkUI_FindAccessibilityActionArgumentByKey接口暂不需要 + // OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key.c_str(), &value); // 根据当前elementid和无障碍动作类型,发送无障碍事件 - ArkUI_AccessibilityEventType eventType = ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; - Flutter_SendAccessibilityAsyncEvent(elementId, eventType); + switch(action) { + /** Response to a click. 16 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: { + /** Click event, sent after the UI component responds. 1 */ + ArkUI_AccessibilityEventType clickEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_CLICKED; + Flutter_SendAccessibilityAsyncEvent(elementId, clickEventType); + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: click("< action: longclick("< action: focus("< action: clearfocus("< action: scroll forward("< action: scroll backward("< action: copy("< action: paste("< action: cut("<selectTextBegin, TextEnd, and TextInForward + * parameters to select a text segment in the text box. 8192 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: select text("< action: set text("< action: set cursor position("< action: invalid("< c++层传递 - * NOTE: flutter语义树的更新过程,获取每个语义节点的更新属性 - */ + /** 获取并分析每个语义节点的更新属性 */ for (auto& item : update) { // 获取当前更新的节点node const flutter::SemanticsNode& node = item.second; printTest(node); // print node info for debugging // 构建flutter无障碍语义节点树 - if(flutterSemanticsTree_.count(node.id) == 0) { + if (flutterSemanticsTree_.count(node.id) == 0) { flutterSemanticsTree_.insert({node.id, node}); } else { FML_DLOG(ERROR) << "UpdateSemantics -> flutterSemanticsTree_: node.id=" - << node.id<<" has already exists !"; + << node.id << " has already exists !"; } // 若当前更新节点是隐藏的,则跳过 - if (node.HasFlag(FLAGS_::kIsHidden)) { + if (node.HasFlag(FLAGS_::kIsHidden)) { continue; } // 判断flutter节点是否获焦 - if (IsNodeFocusable(node)) { + if (IsNodeFocusable(node)) { FML_DLOG(INFO) << "UpdateSemantics -> flutterNode is focusable, node.id=" << node.id; } - //获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 + // 获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 int32_t childNodeCount = node.childrenInTraversalOrder.size(); for (int32_t i = 0; i < childNodeCount; i++) { parentChildIdVec.emplace_back( @@ -956,41 +1021,47 @@ void OhosAccessibilityBridge::updateSemantics( << ", " << node.childrenInTraversalOrder[i] << ")"; } - //TODO: 若该对象是输入焦点节点,且发生更新变化,则发送给os有关它的信息 - // std::shared_ptr - // inputFocusedSemanticsNode; // 当前输入焦点节点 - // std::shared_ptr - // lastInputFocusedSemanticsNode; // 上一个输入焦点节点 - // bool isHadFlag = true; - // if (inputFocusedSemanticsNode != nullptr && - // inputFocusedSemanticsNode->id == node.id && - // (lastInputFocusedSemanticsNode == nullptr || - // lastInputFocusedSemanticsNode->id != inputFocusedSemanticsNode->id)) { - // // 上次输入焦点节点 -> 当前输入焦点节点 - // lastInputFocusedSemanticsNode = inputFocusedSemanticsNode; - // // 发送相应的输入焦点改变事件 - // // sendAccessibilityEvent(obtainAccessibilityEvent(object.id, - // // AccessibilityEvent.TYPE_VIEW_FOCUSED)); - // } else if (inputFocusedSemanticsNode == nullptr) { - // // There's no TYPE_VIEW_CLEAR_FOCUSED event, so if the current input focus - // // becomes null, then we just set the last one to null too, so that it - // // sends the event again when something regains focus. - // lastInputFocusedSemanticsNode = nullptr; - // } + // TODO: 若该对象是输入焦点节点,且发生更新变化,则发送给os有关它的信息 + // std::shared_ptr + // inputFocusedSemanticsNode; // 当前输入焦点节点 + // std::shared_ptr + // lastInputFocusedSemanticsNode; // 上一个输入焦点节点 + // bool isHadFlag = true; + // if (inputFocusedSemanticsNode != nullptr && + // inputFocusedSemanticsNode->id == node.id && + // (lastInputFocusedSemanticsNode == nullptr || + // lastInputFocusedSemanticsNode->id != + // inputFocusedSemanticsNode->id)) { + // // 上次输入焦点节点 -> 当前输入焦点节点 + // lastInputFocusedSemanticsNode = inputFocusedSemanticsNode; + // // 发送相应的输入焦点改变事件 + // // sendAccessibilityEvent(obtainAccessibilityEvent(object.id, + // // AccessibilityEvent.TYPE_VIEW_FOCUSED)); + // } else if (inputFocusedSemanticsNode == nullptr) { + // // There's no TYPE_VIEW_CLEAR_FOCUSED event, so if the current input + // focus + // // becomes null, then we just set the last one to null too, so that it + // // sends the event again when something regains focus. + // lastInputFocusedSemanticsNode = nullptr; + // } // if (inputFocusedSemanticsNode != nullptr && // inputFocusedSemanticsNode->id == node.id && isHadFlag && // node.HasFlag(FLAGS_::kIsTextField) // // If we have a TextField that has InputFocus, we should avoid - // // announcing it if something else we track has a11y focus. This needs - // // to still work when, e.g., IME has a11y focus or the "PASTE" popup is + // // announcing it if something else we track has a11y focus. This + // needs + // // to still work when, e.g., IME has a11y focus or the "PASTE" popup + // is // // used though. See more discussion at // // https://github.com/flutter/flutter/issues/23180 // && (accessibilityFocusedSemanticsNode == nullptr || // (accessibilityFocusedSemanticsNode->id == // inputFocusedSemanticsNode->id))) { - // // 这里写输入框更新文字内容,将老旧的文本替换为新输入文字,并发送textchange事件 - // // AccessibilityEvent event = createTextChangedEvent(object.id, oldValue, + // // + // 这里写输入框更新文字内容,将老旧的文本替换为新输入文字,并发送textchange事件 + // // AccessibilityEvent event = createTextChangedEvent(object.id, + // oldValue, // // newValue); sendAccessibilityEvent(event); // // todo:若当前textselection部分和之前的textselection部分不同,则触发 @@ -1000,7 +1071,8 @@ void OhosAccessibilityBridge::updateSemantics( // previousTextSelectionExtent != node.textSelectionExtent) { // // 创建并发送textselection改变事件 // // AccessibilityEvent selectionEvent = obtainAccessibilityEvent( - // // object.id, AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); + // // object.id, + // AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); // // selectionEvent.getText().add(newValue); // // selectionEvent.setFromIndex(object.textSelectionBase); // // selectionEvent.setToIndex(object.textSelectionExtent); @@ -1040,35 +1112,34 @@ void OhosAccessibilityBridge::updateSemantics( // TODO: ... } - //打印flutter语义树的不同节点的属性信息 - for (const auto& item : flutterSemanticsTree_) { - FML_DLOG(INFO) << "flutterSemanticsTree_ -> {" << item.first << ", " - << item.second.id << "}"; - } - for (const auto& item : parentChildIdVec) { - FML_DLOG(INFO) << "parentChildIdVec -> (" << item.first << ", " - << item.second << ")"; - } + // 打印flutter语义树的不同节点的属性信息 + for (const auto& item : flutterSemanticsTree_) { + FML_DLOG(INFO) << "flutterSemanticsTree_ -> {" << item.first << ", " + << item.second.id << "}"; + } + for (const auto& item : parentChildIdVec) { + FML_DLOG(INFO) << "parentChildIdVec -> (" << item.first << ", " + << item.second << ")"; + } } } /** 获取当前flutter节点的组件类型,并映射为arkui组件 */ std::string OhosAccessibilityBridge::GetNodeComponentType( const flutter::SemanticsNode& node) { - if (node.HasFlag(FLAGS_::kIsButton)) { return "Button"; } if (node.HasFlag(FLAGS_::kIsTextField)) { - //arkui没有textfield,这里直接透传 + // arkui没有textfield,这里直接透传 return "TextInput"; } - if(node.HasFlag(FLAGS_::kIsMultiline)) { - //arkui没有多行文本textfield,这里直接透传 + if (node.HasFlag(FLAGS_::kIsMultiline)) { + // arkui没有多行文本textfield,这里直接透传 return "TextArea"; - } + } if (node.HasFlag(FLAGS_::kIsLink)) { return "Link"; @@ -1089,7 +1160,7 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( if (node.HasFlag(FLAGS_::kHasCheckedState)) { if (node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup)) { - //arkui没有RadioButton,这里透传为Radio + // arkui没有RadioButton,这里透传为Radio return "Radio"; } else { return "Checkbox"; @@ -1097,12 +1168,12 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( } if (node.HasFlag(FLAGS_::kHasToggledState)) { - //arkui没有ToggleSwitch,这里透传为Toggle + // arkui没有ToggleSwitch,这里透传为Toggle return "Toggle"; } - if ((!node.label.empty() || !node.tooltip.empty() || (!node.hint.empty()) && - node.id != 0)) { + if ((!node.label.empty() || !node.tooltip.empty() || !node.hint.empty()) && + node.id != 0) { return "Text"; } @@ -1141,9 +1212,10 @@ void OhosAccessibilityBridge::removeSemanticsNode( FML_DLOG(INFO) << "Attempted to remove a node that is not in the tree."; } int32_t nodeToBeRemovedParentId = GetParentId(nodeToBeRemoved.id); - for(auto it=parentChildIdVec.begin(); it!=parentChildIdVec.end(); it++) { - if(it->first == nodeToBeRemovedParentId && it->second == nodeToBeRemoved.id) { - parentChildIdVec.erase(it); + for (auto it = parentChildIdVec.begin(); it != parentChildIdVec.end(); it++) { + if (it->first == nodeToBeRemovedParentId && + it->second == nodeToBeRemoved.id) { + parentChildIdVec.erase(it); } } if (nodeToBeRemoved.platformViewId != -1) { -- Gitee From 8102ec62c3b5d073778e0bde3dd008f98353c9ac Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 19 Sep 2024 22:14:49 +0800 Subject: [PATCH 030/151] =?UTF-8?q?feat:=E5=AE=9E=E7=8E=B0DispatchSemantic?= =?UTF-8?q?sAction=E6=8E=A5=E5=8F=A3=E5=AF=B9=E4=BA=8Eflutter=E5=B1=8F?= =?UTF-8?q?=E5=B9=95=E5=8A=A8=E4=BD=9C=E8=A7=A3=E6=9E=90,=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81=E8=B0=83=E7=94=A8?= =?UTF-8?q?=E9=93=BEdebug=E6=89=93=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- runtime/runtime_controller.cc | 2 +- shell/common/platform_view.cc | 1 + .../ohos_accessibility_bridge.cpp | 73 +++++++++++-------- .../accessibility/ohos_accessibility_bridge.h | 6 +- .../src/main/ets/view/AccessibilityBridge.ets | 5 -- .../ohos/napi/platform_view_ohos_napi.cpp | 8 +- shell/platform/ohos/platform_view_ohos.cpp | 2 +- 7 files changed, 57 insertions(+), 40 deletions(-) diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index f39452f9ea..520c6ff5c5 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -286,9 +286,9 @@ bool RuntimeController::DispatchSemanticsAction(int32_t id, TRACE_EVENT1("flutter", "RuntimeController::DispatchSemanticsAction", "mode", "basic"); if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) { + FML_DLOG(INFO) << "RuntimeController::DispatchSemanticsAction, id="< id:"<(action); delegate_.OnPlatformViewDispatchSemanticsAction(id, action, std::move(args)); } diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 3b02ab1f1b..888d6b49be 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -12,16 +12,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -#include "ohos_accessibility_bridge.h" #include +#include "ohos_accessibility_bridge.h" #include "flutter/fml/logging.h" #include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/ohos/ohos_shell_holder.h" #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/core/SkScalar.h" +#include "flutter/shell/common/platform_view.h" -#define SHELL_HOLDER (reinterpret_cast(shell_holder)) +#define SHELL_HOLDER (reinterpret_cast(nativeShellHolder_)) namespace flutter { OhosAccessibilityBridge OhosAccessibilityBridge::bridgeInstance; @@ -658,63 +658,61 @@ int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( } /** 将arkui的action类型转化为flutter的action类型 */ -int32_t ActionTypeConversion(ArkUI_Accessibility_ActionType arkui_action) { +flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions(ArkUI_Accessibility_ActionType arkui_action) { // 部分arkui操作和flutter操作的映射,其余action暂时无法适配, 这里先return 0 switch (arkui_action) { case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: - return static_cast(ACTIONS_::kTap); + return ACTIONS_::kTap; case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: - return static_cast(ACTIONS_::kLongPress); + return ACTIONS_::kLongPress; case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: - return static_cast(ACTIONS_::kScrollUp); + return ACTIONS_::kScrollUp; case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: - return static_cast(ACTIONS_::kScrollDown); + return ACTIONS_::kScrollDown; case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: - return static_cast(ACTIONS_::kCopy); + return ACTIONS_::kCopy; case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: - return static_cast(ACTIONS_::kCut); + return ACTIONS_::kCut; case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: - return static_cast(ACTIONS_::kDidGainAccessibilityFocus); + return ACTIONS_::kDidGainAccessibilityFocus; case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: - return static_cast(ACTIONS_::kDidLoseAccessibilityFocus); + return ACTIONS_::kDidLoseAccessibilityFocus; // Text selection action, requiring the setting of selectTextBegin, // TextEnd, and TextInForward parameters to select a text // segment in the text box. */ case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: - return static_cast(ACTIONS_::kSetSelection); + return ACTIONS_::kSetSelection; case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: - return static_cast(ACTIONS_::kSetText); + return ACTIONS_::kSetText; default: - return static_cast( - ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID); + return ACTIONS_::kDismiss; } } -void DispatchSemanticsAction(int32_t id, flutter::SemanticsAction action) { +void OhosAccessibilityBridge::DispatchSemanticsAction(int32_t id, flutter::SemanticsAction action, fml::MallocMapping args) { FML_DLOG(INFO) << "DispatchSemanticsAction is called"; // TODO: ... 发送语义动作解析 - // SHELL_HOLDER->GetPlatformView()->DispatchSemanticsAction(id, action, {}); + SHELL_HOLDER->GetPlatformView()->PlatformView::DispatchSemanticsAction(id, action, {}); } /** @@ -747,6 +745,10 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( ArkUI_AccessibilityEventType clickEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_CLICKED; Flutter_SendAccessibilityAsyncEvent(elementId, clickEventType); FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: click("< flutter对应节点的屏幕点击 + ACTIONS_ flutterTapAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), flutterTapAction, {}); break; } /** Response to a long click. 32 */ @@ -755,6 +757,10 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( ArkUI_AccessibilityEventType longClickEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_LONG_CLICKED; Flutter_SendAccessibilityAsyncEvent(elementId, longClickEventType); FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: longclick("< flutter对应节点的屏幕动作 + ACTIONS_ flutterLongPressAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), flutterLongPressAction, {}); break; } /** Accessibility focus acquisition. 64 */ @@ -763,6 +769,10 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( ArkUI_AccessibilityEventType focusEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; Flutter_SendAccessibilityAsyncEvent(elementId, focusEventType); FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: focus("< flutter对应节点的获焦 + ACTIONS_ flutterGainFocusAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), flutterGainFocusAction, {}); break; } /** Accessibility focus clearance. 128 */ @@ -771,6 +781,10 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( ArkUI_AccessibilityEventType clearFocusEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED; Flutter_SendAccessibilityAsyncEvent(elementId, clearFocusEventType); FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: clearfocus("< flutter对应节点的失焦 + ACTIONS_ flutterLoseFocusAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), flutterLoseFocusAction, {}); break; } /** Forward scroll action. 256 */ @@ -894,7 +908,7 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( OH_ArkUI_SendAccessibilityAsyncEvent(provider_, eventInfo, callback); // 7.销毁新创建的elementinfo - // OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); + OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); FML_DLOG(INFO) << "OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent is end"; @@ -933,8 +947,8 @@ void OhosAccessibilityBridge::updateSemantics( FML_DLOG(INFO) << ("OhosAccessibilityBridge::updateSemantics is called"); // 每次flutter语义节点更新,需要清空语义树容器节点信息 - flutterSemanticsTree_.clear(); - parentChildIdVec.clear(); + // flutterSemanticsTree_.clear(); + // parentChildIdVec.clear(); std::set visitedObjs; std::vector newRoutes; @@ -995,12 +1009,13 @@ void OhosAccessibilityBridge::updateSemantics( printTest(node); // print node info for debugging // 构建flutter无障碍语义节点树 - if (flutterSemanticsTree_.count(node.id) == 0) { - flutterSemanticsTree_.insert({node.id, node}); - } else { - FML_DLOG(ERROR) << "UpdateSemantics -> flutterSemanticsTree_: node.id=" - << node.id << " has already exists !"; - } + flutterSemanticsTree_.insert({node.id, node}); + // if (flutterSemanticsTree_.count(node.id) == 0) { + // flutterSemanticsTree_.insert({node.id, node}); + // } else { + // FML_DLOG(ERROR) << "UpdateSemantics -> flutterSemanticsTree_: node.id=" + // << node.id << " has already exists !"; + // } // 若当前更新节点是隐藏的,则跳过 if (node.HasFlag(FLAGS_::kIsHidden)) { @@ -1133,7 +1148,7 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( if (node.HasFlag(FLAGS_::kIsTextField)) { // arkui没有textfield,这里直接透传 - return "TextInput"; + return "TextField"; } if (node.HasFlag(FLAGS_::kIsMultiline)) { diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 3fdee2ca8c..9e9aa52057 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -46,9 +46,9 @@ class OhosAccessibilityBridge { static OhosAccessibilityBridge* GetInstance(); bool isOhosAccessibilityEnabled_; - int64_t nativeShellHolder; + int64_t nativeShellHolder_; - void DispatchSemanticsAction(int32_t id, flutter::SemanticsAction action); + void DispatchSemanticsAction(int32_t id, flutter::SemanticsAction action, fml::MallocMapping args); void announce(std::unique_ptr& message); @@ -92,7 +92,7 @@ class OhosAccessibilityBridge { flutter::SemanticsNode getFlutterRootSemanticsNode(); bool IsNodeFocusable(const flutter::SemanticsNode& node); std::string GetNodeComponentType(const flutter::SemanticsNode& node); - int32_t ActionTypeConversion(ArkUI_Accessibility_ActionType arkui_action); + flutter::SemanticsAction ArkuiActionsToFlutterActions(ArkUI_Accessibility_ActionType arkui_action); void onWindowNameChange(flutter::SemanticsNode route); diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets index 1ce465a8a4..b3972c1213 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets @@ -58,11 +58,6 @@ export default class AccessibilityBridge implements AccessibilityMessageHandler Log.d(TAG, "AccessibilityBridge.ets accessibilityStateChange is called"); } - /** - * TODO lack of AccessibilityManager.AccessibilityStateChangeListener - * Listener that is notified when accessibility is turned on/off. - */ - } export enum Action { diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index fa9c2959bb..8465711624 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1925,6 +1925,11 @@ napi_value PlatformViewOHOSNapi::nativeSetSemanticsEnabled(napi_env env, napi_ca OHOS_SHELL_HOLDER->GetPlatformView()->SetSemanticsEnabled(enabled); FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeSetSemanticsEnabled " "OHOS_SHELL_HOLDER->GetPlatformView()->SetSemanticsEnabled= "<nativeShellHolder_ = shell_holder; + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeSetSemanticsEnabled -> shell_holder:"<nativeShellHolder = shell_holder; + ohosAccessibilityBridge->nativeShellHolder_ = shell_holder; + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeGetShellHolderId -> shell_holder:"< id=" << id << ", action=" << action << ", actionDataLenth" << actionDataLenth; auto args_vector = fml::MallocMapping::Copy(actionData, actionDataLenth); -- Gitee From 3bbad2d37a6160edbbea6192608e347984937d27 Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 20 Sep 2024 12:00:06 +0800 Subject: [PATCH 031/151] =?UTF-8?q?feat:=E5=AE=8C=E5=96=84ExecuteAccessibi?= =?UTF-8?q?lityAction=E6=8E=A5=E5=8F=A3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 110 +++++++++++++++--- .../accessibility/ohos_accessibility_bridge.h | 10 +- 2 files changed, 101 insertions(+), 19 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 888d6b49be..27e583d410 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -705,6 +705,7 @@ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions(A return ACTIONS_::kSetText; default: + //TODO might not match to the valid action in arkui return ACTIONS_::kDismiss; } } @@ -734,113 +735,178 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } - // NOTE: OH_ArkUI_FindAccessibilityActionArgumentByKey接口暂不需要 - // OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key.c_str(), &value); + //获取当前elementid对应的flutter语义节点 + auto flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); // 根据当前elementid和无障碍动作类型,发送无障碍事件 switch(action) { /** Response to a click. 16 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: { /** Click event, sent after the UI component responds. 1 */ - ArkUI_AccessibilityEventType clickEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_CLICKED; + auto clickEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_CLICKED; Flutter_SendAccessibilityAsyncEvent(elementId, clickEventType); FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: click("< flutter对应节点的屏幕点击 - ACTIONS_ flutterTapAction = ArkuiActionsToFlutterActions(action); + auto flutterTapAction = ArkuiActionsToFlutterActions(action); DispatchSemanticsAction(static_cast(elementId), flutterTapAction, {}); break; } + /** Response to a long click. 32 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: { /** Long click event, sent after the UI component responds. 2 */ - ArkUI_AccessibilityEventType longClickEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_LONG_CLICKED; + auto longClickEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_LONG_CLICKED; Flutter_SendAccessibilityAsyncEvent(elementId, longClickEventType); FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: longclick("< flutter对应节点的屏幕动作 - ACTIONS_ flutterLongPressAction = ArkuiActionsToFlutterActions(action); + auto flutterLongPressAction = ArkuiActionsToFlutterActions(action); DispatchSemanticsAction(static_cast(elementId), flutterLongPressAction, {}); break; } + /** Accessibility focus acquisition. 64 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: { + //解析arkui的获焦 -> flutter对应节点的获焦 + auto flutterGainFocusAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), flutterGainFocusAction, {}); + /** Accessibility focus event, sent after the UI component responds. 32768 */ - ArkUI_AccessibilityEventType focusEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; + auto focusEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; Flutter_SendAccessibilityAsyncEvent(elementId, focusEventType); FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: focus("< flutter对应节点的获焦 - ACTIONS_ flutterGainFocusAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), flutterGainFocusAction, {}); + if (flutterNode.HasAction(ACTIONS_::kIncrease) + || flutterNode.HasAction(ACTIONS_::kDecrease)) { + Flutter_SendAccessibilityAsyncEvent(elementId, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + } + break; } + /** Accessibility focus clearance. 128 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: { + //解析arkui的失焦 -> flutter对应节点的失焦 + auto flutterLoseFocusAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), flutterLoseFocusAction, {}); + /** Accessibility focus cleared event, sent after the UI component responds. 65536 */ - ArkUI_AccessibilityEventType clearFocusEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED; + auto clearFocusEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED; Flutter_SendAccessibilityAsyncEvent(elementId, clearFocusEventType); FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: clearfocus("< flutter对应节点的失焦 - ACTIONS_ flutterLoseFocusAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), flutterLoseFocusAction, {}); break; } + /** Forward scroll action. 256 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: { /** Scrolled event, sent when a scrollable component experiences a scroll event. 4096 */ ArkUI_AccessibilityEventType scrollEventType1 = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: scroll forward("<(elementId), flutterScrollUpAction, {}); + + } else if (flutterNode.HasAction(ACTIONS_::kScrollLeft)) { + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kScrollLeft, {}); + + } else if (flutterNode.HasAction(ACTIONS_::kIncrease)) { + flutterNode.value = flutterNode.increasedValue; + flutterNode.valueAttributes = flutterNode.increasedValueAttributes; + //TODO: Flutter_SendAccessibilityAsyncEvent() -> selected eventtype + Flutter_SendAccessibilityAsyncEvent(elementId, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kIncrease, {}); + + } else {} break; } + /** Backward scroll action. 512 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: { /** Scrolled event, sent when a scrollable component experiences a scroll event. 4096 */ ArkUI_AccessibilityEventType scrollEventType2 = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType2); FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: scroll backward("<(elementId), flutterScrollDownAction, {}); + + } else if (flutterNode.HasAction(ACTIONS_::kScrollRight)) { + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kScrollRight, {}); + + } else if (flutterNode.HasAction(ACTIONS_::kDecrease)) { + flutterNode.value = flutterNode.decreasedValue; + flutterNode.valueAttributes = flutterNode.decreasedValueAttributes; + //TODO: Flutter_SendAccessibilityAsyncEvent() -> selected eventtype + Flutter_SendAccessibilityAsyncEvent(elementId, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kDecrease, {}); + + } else {} break; } + /** Copy action for text content. 1024 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: { FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: copy("<(elementId), ACTIONS_::kCopy, {}); break; } + /** Paste action for text content. 2048 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE: { FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: paste("<(elementId), ACTIONS_::kPaste, {}); break; } + /** Cut action for text content. 4096 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: cut("<(elementId), ACTIONS_::kCut, {}); break; + /** Text selection action, requiring the setting of selectTextBegin, TextEnd, and TextInForward * parameters to select a text segment in the text box. 8192 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: { FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: select text("< action: set text("< action: set cursor position("< action: invalid("<& message); - void updateSemantics(flutter::SemanticsNodeUpdates update, - flutter::CustomAccessibilityActionUpdates actions); - // obtain the flutter semnatics node flutter::SemanticsNode getOrCreateFlutterSemanticsNode(int32_t id); @@ -94,6 +95,9 @@ class OhosAccessibilityBridge { std::string GetNodeComponentType(const flutter::SemanticsNode& node); flutter::SemanticsAction ArkuiActionsToFlutterActions(ArkUI_Accessibility_ActionType arkui_action); + void PerformSetText(flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments); + void PerformSelectText(flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments); + void onWindowNameChange(flutter::SemanticsNode route); void removeSemanticsNode(flutter::SemanticsNode nodeToBeRemoved); -- Gitee From c544a90f86ecde5f9501acef358e46cbbfd2d68d Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 20 Sep 2024 21:07:36 +0800 Subject: [PATCH 032/151] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9=E8=B7=B3?= =?UTF-8?q?=E8=BD=AC=E6=96=B0=E9=A1=B5=E9=9D=A2updateSemantics=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E6=9B=B4=E6=96=B0=E8=AF=AD=E4=B9=89=E6=A0=91bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 452 +++++++++--------- 1 file changed, 229 insertions(+), 223 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 27e583d410..5f583bf498 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -33,6 +33,207 @@ OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() { return &OhosAccessibilityBridge::bridgeInstance; } +/** + * NOTE: 从dart侧传递到c++侧的flutter语义树节点更新过程 + */ +void OhosAccessibilityBridge::updateSemantics( + flutter::SemanticsNodeUpdates update, + flutter::CustomAccessibilityActionUpdates actions) { + FML_DLOG(INFO) << ("OhosAccessibilityBridge::updateSemantics is called"); + + // 每次flutter语义节点更新,需要清空语义树容器节点信息 + // flutterSemanticsTree_.clear(); + // parentChildIdVec.clear(); + + std::set visitedObjs; + std::vector newRoutes; + + // Dispatch a TYPE_WINDOW_STATE_CHANGED event if the most recent route id + // changed from the + // previously cached route id. + // Finds the last route that is not in the previous routes. + // SEMANTICS_NODE_ lastAdded; + // lastAdded.id = -2; + // for (const auto& _node : newRoutes) { + // if (!flutterNavigationStack[_node.id]) { + // lastAdded = _node; + // } + // } + // // If all the routes are in the previous route, get the last route. + // if (lastAdded.id == -2 && newRoutes.size() > 0) { + // lastAdded = newRoutes[newRoutes.size() - 1]; + // } + + // There are two cases if lastAdded != nil + // 1. lastAdded is not in previous routes. In this case, + // lastAdded.id != previousRouteId + // 2. All new routes are in previous routes and + // lastAdded = newRoutes.last. + // In the first case, we need to announce new route. In the second case, + // we need to announce if one list is shorter than the other. + // if (lastAdded.id != -2 && (lastAdded.id != previousRouteId || + // newRoutes.size() != + // flutterNavigationStack.size())) { + // previousRouteId = lastAdded.id; + // onWindowNameChange(lastAdded); // todo + // } + // flutterNavigationStack.clear(); + // for (const auto& _node : newRoutes) { + // flutterNavigationStack.emplace_back(_node.id); + // } + + // for (const auto& item : flutterSemanticsTree_) { + // SEMANTICS_NODE_ obj = item.second; + // if (visitedObjs.find(obj) == visitedObjs.end()) { + // removeSemanticsNode(obj); + // flutterSemanticsTree_.erase(item.first); + // } + // } + + /** 获取并分析每个语义节点的更新属性 */ + for (auto& item : update) { + // 获取当前更新的节点node + const flutter::SemanticsNode& node = item.second; + printTest(node); // print node info for debugging + + /** + * 构建flutter无障碍语义节点树 + * NOTE: 若使用flutterSemanticsTree_.insert({node.id, node})方式 + * 来添加新增的语义节点会导致已有key值自动忽略,不会更新原有key对应的value + */ + flutterSemanticsTree_[node.id] = node; + + // 若当前更新节点是隐藏的,则跳过 + if (node.HasFlag(FLAGS_::kIsHidden)) { + continue; + } + // 判断flutter节点是否获焦 + if (IsNodeFocusable(node)) { + FML_DLOG(INFO) << "UpdateSemantics -> flutterNode is focusable, node.id=" + << node.id; + } + + // 获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 + int32_t childNodeCount = node.childrenInTraversalOrder.size(); + for (int32_t i = 0; i < childNodeCount; i++) { + parentChildIdVec.emplace_back( + std::make_pair(node.id, node.childrenInTraversalOrder[i])); + FML_DLOG(INFO) << "UpdateSemantics parentChildIdMap -> (" << node.id + << ", " << node.childrenInTraversalOrder[i] << ")"; + } + + // TODO: 若该对象是输入焦点节点,且发生更新变化,则发送给os有关它的信息 + // std::shared_ptr + // inputFocusedSemanticsNode; // 当前输入焦点节点 + // std::shared_ptr + // lastInputFocusedSemanticsNode; // 上一个输入焦点节点 + // bool isHadFlag = true; + // if (inputFocusedSemanticsNode != nullptr && + // inputFocusedSemanticsNode->id == node.id && + // (lastInputFocusedSemanticsNode == nullptr || + // lastInputFocusedSemanticsNode->id != + // inputFocusedSemanticsNode->id)) { + // // 上次输入焦点节点 -> 当前输入焦点节点 + // lastInputFocusedSemanticsNode = inputFocusedSemanticsNode; + // // 发送相应的输入焦点改变事件 + // // sendAccessibilityEvent(obtainAccessibilityEvent(object.id, + // // AccessibilityEvent.TYPE_VIEW_FOCUSED)); + // } else if (inputFocusedSemanticsNode == nullptr) { + // // There's no TYPE_VIEW_CLEAR_FOCUSED event, so if the current input + // focus + // // becomes null, then we just set the last one to null too, so that it + // // sends the event again when something regains focus. + // lastInputFocusedSemanticsNode = nullptr; + // } + + // if (inputFocusedSemanticsNode != nullptr && + // inputFocusedSemanticsNode->id == node.id && isHadFlag && + // node.HasFlag(FLAGS_::kIsTextField) + // // If we have a TextField that has InputFocus, we should avoid + // // announcing it if something else we track has a11y focus. This + // needs + // // to still work when, e.g., IME has a11y focus or the "PASTE" popup + // is + // // used though. See more discussion at + // // https://github.com/flutter/flutter/issues/23180 + // && (accessibilityFocusedSemanticsNode == nullptr || + // (accessibilityFocusedSemanticsNode->id == + // inputFocusedSemanticsNode->id))) { + // // + // 这里写输入框更新文字内容,将老旧的文本替换为新输入文字,并发送textchange事件 + // // AccessibilityEvent event = createTextChangedEvent(object.id, + // oldValue, + // // newValue); sendAccessibilityEvent(event); + + // // todo:若当前textselection部分和之前的textselection部分不同,则触发 + // int32_t previousTextSelectionBase = 0; + // int32_t previousTextSelectionExtent = 1; + // if (previousTextSelectionBase != node.textSelectionBase || + // previousTextSelectionExtent != node.textSelectionExtent) { + // // 创建并发送textselection改变事件 + // // AccessibilityEvent selectionEvent = obtainAccessibilityEvent( + // // object.id, + // AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); + // // selectionEvent.getText().add(newValue); + // // selectionEvent.setFromIndex(object.textSelectionBase); + // // selectionEvent.setToIndex(object.textSelectionExtent); + // // selectionEvent.setItemCount(newValue.length()); + // // sendAccessibilityEvent(selectionEvent); + // } + // } + + // todo: 是否触发滑动操作 + bool didScroll = true; + if (didScroll) { + // 1. 声明并创建accessibilityEvent类型,比如滑动事件 + // 2. + // 获取semanticsNode里scrollPosition、scrollExtensionMax、scrollExtensionMin字段 + // 3. 发送事件中包含上述scroll位置变动信息(如下所示) + // int32_t scrollChildren = 0; + // int32_t scrollIndex = 0; + // double scrollPosition = std::nan(""); + // double scrollExtentMax = std::nan(""); + // double scrollExtentMin = std::nan(""); + int32_t scrollChildren = 0; + if (scrollChildren > 0) { + // todo 发送事件,包含scrollChildren数量、scrollIndex + // int visibleChildren = 0; + // // handle hidden children at the beginning and end of the list. + // for (flutter::SemanticsNode child : node.childrenInHitTestOrder) { + // if (!child.hasFlag(Flag.IS_HIDDEN)) { + // visibleChildren += 1; + // } + // } + } + // sendAccessibilityEvent(event) + } + + // 判断是否触发liveRegion活动区,当前节点是否活跃(优先级低) + if (node.HasFlag(FLAGS_::kIsLiveRegion)) { + // TODO: ... + } + } + + // TODO: 遍历更新的actions,并将所有的actions的id添加进actionMap + for (const auto& item : actions) { + const flutter::CustomAccessibilityAction action = item.second; + printTestActions(action); + actions_mp_[action.id] = action; + } + + // 打印flutter语义树的不同节点的属性信息 + for (const auto& item : flutterSemanticsTree_) { + FML_DLOG(INFO) << "flutterSemanticsTree_ -> {" << item.first << ", " + << item.second.id << "}"; + } + for (const auto& item : parentChildIdVec) { + FML_DLOG(INFO) << "parentChildIdVec -> (" << item.first << ", " + << item.second << ")"; + } + + FML_DLOG(INFO) << "=== UpdateSemantics is end ==="; +} + void OhosAccessibilityBridge::announce(std::unique_ptr& message) { // 创建并设置屏幕朗读事件 ArkUI_AccessibilityEventInfo* announceEventInfo = @@ -69,7 +270,7 @@ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode( return flutterSemanticsTree_.at(id); FML_DLOG(INFO) << "getOrCreateFlutterSemanticsNode get node.id=" << id; } else { - FML_DLOG(INFO) + FML_DLOG(ERROR) << "getOrCreateFlutterSemanticsNode flutterSemanticsTree_ = null" << id; return flutter::SemanticsNode{}; } @@ -198,17 +399,23 @@ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, float top, float right, float bottom) { - if (screenRectMap_.find(flutterNodeId) == screenRectMap_.end()) { - screenRectMap_.insert( + screenRectMap_.insert( {flutterNodeId, std::make_pair(std::make_pair(left, top), std::make_pair(right, bottom))}); FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId << ", <" << left << ", " << top << ", " << right << ", " << bottom << "> } is succeed"; - } else { - FML_DLOG(ERROR) << "SetAbsoluteScreenRect -> flutterNodeId=" - << flutterNodeId << " already exists !"; - } + // if (screenRectMap_.find(flutterNodeId) == screenRectMap_.end()) { + // screenRectMap_.insert( + // {flutterNodeId, std::make_pair(std::make_pair(left, top), + // std::make_pair(right, bottom))}); + // FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId + // << ", <" << left << ", " << top << ", " << right << ", " + // << bottom << "> } is succeed"; + // } else { + // FML_DLOG(ERROR) << "SetAbsoluteScreenRect -> flutterNodeId=" + // << flutterNodeId << " already exists !"; + // } } std::pair, std::pair> @@ -315,7 +522,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( int32_t top = static_cast(flutterNode.rect.fTop); int32_t right = static_cast(flutterNode.rect.fRight); int32_t bottom = static_cast(flutterNode.rect.fBottom); - ArkUI_AccessibleRect rect = {left, top, right, bottom}; // debug + ArkUI_AccessibleRect rect = {left, top, right, bottom}; OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect); // 设置elementinfo的action类型 @@ -800,11 +1007,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( /** Forward scroll action. 256 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: { - /** Scrolled event, sent when a scrollable component experiences a scroll event. 4096 */ - ArkUI_AccessibilityEventType scrollEventType1 = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; - Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: scroll forward("<(elementId), ACTIONS_::kIncrease, {}); } else {} + + /** Scrolled event, sent when a scrollable component experiences a scroll event. 4096 */ + // ArkUI_AccessibilityEventType scrollEventType1 = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + // Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); + // FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: scroll forward("< action: scroll backward("<(elementId), ACTIONS_::kDecrease, {}); } else {} + + /** Scrolled event, sent when a scrollable component experiences a scroll event. 4096 */ + // ArkUI_AccessibilityEventType scrollEventType2 = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + // Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType2); + // FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: scroll backward("< visitedObjs; - std::vector newRoutes; - - // 遍历更新的actions,并将所有的actions的id添加进actionMap - for (const auto& item : actions) { - const flutter::CustomAccessibilityAction action = item.second; - printTestActions(action); - actions_mp_[action.id] = action; - } - - // Dispatch a TYPE_WINDOW_STATE_CHANGED event if the most recent route id - // changed from the - // previously cached route id. - // Finds the last route that is not in the previous routes. - // SEMANTICS_NODE_ lastAdded; - // lastAdded.id = -2; - // for (const auto& _node : newRoutes) { - // if (!flutterNavigationStack[_node.id]) { - // lastAdded = _node; - // } - // } - // // If all the routes are in the previous route, get the last route. - // if (lastAdded.id == -2 && newRoutes.size() > 0) { - // lastAdded = newRoutes[newRoutes.size() - 1]; - // } - - // There are two cases if lastAdded != nil - // 1. lastAdded is not in previous routes. In this case, - // lastAdded.id != previousRouteId - // 2. All new routes are in previous routes and - // lastAdded = newRoutes.last. - // In the first case, we need to announce new route. In the second case, - // we need to announce if one list is shorter than the other. - // if (lastAdded.id != -2 && (lastAdded.id != previousRouteId || - // newRoutes.size() != - // flutterNavigationStack.size())) { - // previousRouteId = lastAdded.id; - // onWindowNameChange(lastAdded); // todo - // } - // flutterNavigationStack.clear(); - // for (const auto& _node : newRoutes) { - // flutterNavigationStack.emplace_back(_node.id); - // } - - // for (const auto& item : flutterSemanticsTree_) { - // SEMANTICS_NODE_ obj = item.second; - // if (visitedObjs.find(obj) == visitedObjs.end()) { - // removeSemanticsNode(obj); - // flutterSemanticsTree_.erase(item.first); - // } - // } - - /** 获取并分析每个语义节点的更新属性 */ - for (auto& item : update) { - // 获取当前更新的节点node - const flutter::SemanticsNode& node = item.second; - printTest(node); // print node info for debugging - - // 构建flutter无障碍语义节点树 - flutterSemanticsTree_.insert({node.id, node}); - // if (flutterSemanticsTree_.count(node.id) == 0) { - // flutterSemanticsTree_.insert({node.id, node}); - // } else { - // FML_DLOG(ERROR) << "UpdateSemantics -> flutterSemanticsTree_: node.id=" - // << node.id << " has already exists !"; - // } - - // 若当前更新节点是隐藏的,则跳过 - if (node.HasFlag(FLAGS_::kIsHidden)) { - continue; - } - // 判断flutter节点是否获焦 - if (IsNodeFocusable(node)) { - FML_DLOG(INFO) << "UpdateSemantics -> flutterNode is focusable, node.id=" - << node.id; - } - - // 获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 - int32_t childNodeCount = node.childrenInTraversalOrder.size(); - for (int32_t i = 0; i < childNodeCount; i++) { - parentChildIdVec.emplace_back( - std::make_pair(node.id, node.childrenInTraversalOrder[i])); - FML_DLOG(INFO) << "UpdateSemantics parentChildIdMap -> (" << node.id - << ", " << node.childrenInTraversalOrder[i] << ")"; - } - - // TODO: 若该对象是输入焦点节点,且发生更新变化,则发送给os有关它的信息 - // std::shared_ptr - // inputFocusedSemanticsNode; // 当前输入焦点节点 - // std::shared_ptr - // lastInputFocusedSemanticsNode; // 上一个输入焦点节点 - // bool isHadFlag = true; - // if (inputFocusedSemanticsNode != nullptr && - // inputFocusedSemanticsNode->id == node.id && - // (lastInputFocusedSemanticsNode == nullptr || - // lastInputFocusedSemanticsNode->id != - // inputFocusedSemanticsNode->id)) { - // // 上次输入焦点节点 -> 当前输入焦点节点 - // lastInputFocusedSemanticsNode = inputFocusedSemanticsNode; - // // 发送相应的输入焦点改变事件 - // // sendAccessibilityEvent(obtainAccessibilityEvent(object.id, - // // AccessibilityEvent.TYPE_VIEW_FOCUSED)); - // } else if (inputFocusedSemanticsNode == nullptr) { - // // There's no TYPE_VIEW_CLEAR_FOCUSED event, so if the current input - // focus - // // becomes null, then we just set the last one to null too, so that it - // // sends the event again when something regains focus. - // lastInputFocusedSemanticsNode = nullptr; - // } - - // if (inputFocusedSemanticsNode != nullptr && - // inputFocusedSemanticsNode->id == node.id && isHadFlag && - // node.HasFlag(FLAGS_::kIsTextField) - // // If we have a TextField that has InputFocus, we should avoid - // // announcing it if something else we track has a11y focus. This - // needs - // // to still work when, e.g., IME has a11y focus or the "PASTE" popup - // is - // // used though. See more discussion at - // // https://github.com/flutter/flutter/issues/23180 - // && (accessibilityFocusedSemanticsNode == nullptr || - // (accessibilityFocusedSemanticsNode->id == - // inputFocusedSemanticsNode->id))) { - // // - // 这里写输入框更新文字内容,将老旧的文本替换为新输入文字,并发送textchange事件 - // // AccessibilityEvent event = createTextChangedEvent(object.id, - // oldValue, - // // newValue); sendAccessibilityEvent(event); - - // // todo:若当前textselection部分和之前的textselection部分不同,则触发 - // int32_t previousTextSelectionBase = 0; - // int32_t previousTextSelectionExtent = 1; - // if (previousTextSelectionBase != node.textSelectionBase || - // previousTextSelectionExtent != node.textSelectionExtent) { - // // 创建并发送textselection改变事件 - // // AccessibilityEvent selectionEvent = obtainAccessibilityEvent( - // // object.id, - // AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); - // // selectionEvent.getText().add(newValue); - // // selectionEvent.setFromIndex(object.textSelectionBase); - // // selectionEvent.setToIndex(object.textSelectionExtent); - // // selectionEvent.setItemCount(newValue.length()); - // // sendAccessibilityEvent(selectionEvent); - // } - // } - - // todo: 是否触发滑动操作 - bool didScroll = true; - if (didScroll) { - // 1. 声明并创建accessibilityEvent类型,比如滑动事件 - // 2. - // 获取semanticsNode里scrollPosition、scrollExtensionMax、scrollExtensionMin字段 - // 3. 发送事件中包含上述scroll位置变动信息(如下所示) - // int32_t scrollChildren = 0; - // int32_t scrollIndex = 0; - // double scrollPosition = std::nan(""); - // double scrollExtentMax = std::nan(""); - // double scrollExtentMin = std::nan(""); - int32_t scrollChildren = 0; - if (scrollChildren > 0) { - // todo 发送事件,包含scrollChildren数量、scrollIndex - // int visibleChildren = 0; - // // handle hidden children at the beginning and end of the list. - // for (flutter::SemanticsNode child : node.childrenInHitTestOrder) { - // if (!child.hasFlag(Flag.IS_HIDDEN)) { - // visibleChildren += 1; - // } - // } - } - // sendAccessibilityEvent(event) - } - - // 判断是否触发liveRegion活动区,当前节点是否活跃(优先级低) - if (node.HasFlag(FLAGS_::kIsLiveRegion)) { - // TODO: ... - } - - // 打印flutter语义树的不同节点的属性信息 - for (const auto& item : flutterSemanticsTree_) { - FML_DLOG(INFO) << "flutterSemanticsTree_ -> {" << item.first << ", " - << item.second.id << "}"; - } - for (const auto& item : parentChildIdVec) { - FML_DLOG(INFO) << "parentChildIdVec -> (" << item.first << ", " - << item.second << ")"; - } - } -} - /** 获取当前flutter节点的组件类型,并映射为arkui组件 */ std::string OhosAccessibilityBridge::GetNodeComponentType( const flutter::SemanticsNode& node) { @@ -1225,7 +1231,7 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( } if (node.HasFlag(FLAGS_::kIsTextField)) { - // arkui没有textfield,这里直接透传 + // arkui没有textfield,这里直接透传或者传递textinput return "TextField"; } @@ -1319,6 +1325,9 @@ void OhosAccessibilityBridge::printTest(flutter::SemanticsNode node) { FML_DLOG(INFO) << "==================SemanticsNode====================="; SkMatrix _transform = node.transform.asM33(); FML_DLOG(INFO) << "node.id=" << node.id; + FML_DLOG(INFO) << "node.label=" << node.label; + FML_DLOG(INFO) << "node.tooltip=" << node.tooltip; + FML_DLOG(INFO) << "node.hint=" << node.hint; FML_DLOG(INFO) << "node.flags=" << node.flags; FML_DLOG(INFO) << "node.actions=" << node.actions; FML_DLOG(INFO) << "node.rect= {" << node.rect.fLeft << ", " << node.rect.fTop @@ -1357,9 +1366,6 @@ void OhosAccessibilityBridge::printTest(flutter::SemanticsNode node) { FML_DLOG(INFO) << "node.scrollExtentMin=" << node.scrollExtentMin; FML_DLOG(INFO) << "node.elevation=" << node.elevation; FML_DLOG(INFO) << "node.thickness=" << node.thickness; - FML_DLOG(INFO) << "node.label=" << node.label; - FML_DLOG(INFO) << "node.tooltip=" << node.tooltip; - FML_DLOG(INFO) << "node.hint=" << node.hint; FML_DLOG(INFO) << "node.textDirection=" << node.textDirection; FML_DLOG(INFO) << "node.childrenInTraversalOrder.size()=" << node.childrenInTraversalOrder.size(); -- Gitee From c4febefc9d7c3ce404cb4aeca0e36c50b30600ce Mon Sep 17 00:00:00 2001 From: zjxi Date: Sat, 21 Sep 2024 15:40:22 +0800 Subject: [PATCH 033/151] =?UTF-8?q?fix:=E8=A7=A3=E5=86=B3=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E6=97=A0=E9=9A=9C=E7=A2=8D=E6=9C=8D=E5=8A=A1=E5=BC=80?= =?UTF-8?q?=E5=90=AF=E5=90=8E=E5=90=AF=E5=8A=A8app=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E6=84=9F=E7=9F=A5=E5=B9=B6=E8=8E=B7=E5=8F=96=E5=BD=93=E5=89=8D?= =?UTF-8?q?=E6=97=A0=E9=9A=9C=E7=A2=8D=E6=98=AF=E5=90=A6=E5=BC=80=E5=90=AF?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../flutter/src/main/ets/embedding/ohos/FlutterAbility.ets | 7 +++++++ .../flutter/src/main/ets/view/FlutterView.ets | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets index 9e589b21c1..2955ec31e2 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets @@ -110,6 +110,13 @@ export class FlutterAbility extends UIAbility implements Host { if (flutterApplicationInfo.isDebugMode) { this.delegate?.initWindow(); } + + //冷启动对os是否开启无障碍服务进行查询 + let accessibilityState: boolean = accessibility.isOpenAccessibilitySync(); + if(accessibilityState) { + this.delegate?.getFlutterNapi()?.setSemanticsEnabled(accessibilityState); + } + Log.i(TAG, `accessibility isOpen state -> ${JSON.stringify(accessibilityState)}`); } onDestroy() { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index 75b1aee544..0cdeda13dc 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -108,7 +108,7 @@ export class FlutterView { this.mainWindow?.on('avoidAreaChange', this.avoidAreaChangeCallback); this.mainWindow?.on('windowStatusChange', this.windowStatusChangeCallback); - //监听系统是否开启无障碍服务 + //监听系统无障碍服务状态改变 accessibility.on('accessibilityStateChange', (data: boolean) => { Log.i(TAG, `subscribe accessibility state change, result: ${JSON.stringify(data)}`); this.flutterEngine?.getFlutterNapi()?.setSemanticsEnabled(data); -- Gitee From f8ffd0e2d9d756deb67a85dd572e985c45325d03 Mon Sep 17 00:00:00 2001 From: zjxi Date: Sat, 21 Sep 2024 15:43:17 +0800 Subject: [PATCH 034/151] =?UTF-8?q?refactor:=E6=A0=BC=E5=BC=8F=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8E=92=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 303 +++++++++++------- 1 file changed, 191 insertions(+), 112 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 5f583bf498..b417a1e553 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -12,14 +12,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include #include "ohos_accessibility_bridge.h" +#include #include "flutter/fml/logging.h" +#include "flutter/shell/common/platform_view.h" #include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/ohos/ohos_shell_holder.h" #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/core/SkScalar.h" -#include "flutter/shell/common/platform_view.h" #define SHELL_HOLDER (reinterpret_cast(nativeShellHolder_)) namespace flutter { @@ -224,11 +224,11 @@ void OhosAccessibilityBridge::updateSemantics( // 打印flutter语义树的不同节点的属性信息 for (const auto& item : flutterSemanticsTree_) { FML_DLOG(INFO) << "flutterSemanticsTree_ -> {" << item.first << ", " - << item.second.id << "}"; + << item.second.id << "}"; } for (const auto& item : parentChildIdVec) { FML_DLOG(INFO) << "parentChildIdVec -> (" << item.first << ", " - << item.second << ")"; + << item.second << ")"; } FML_DLOG(INFO) << "=== UpdateSemantics is end ==="; @@ -400,11 +400,11 @@ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, float right, float bottom) { screenRectMap_.insert( - {flutterNodeId, std::make_pair(std::make_pair(left, top), - std::make_pair(right, bottom))}); - FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId - << ", <" << left << ", " << top << ", " << right << ", " - << bottom << "> } is succeed"; + {flutterNodeId, std::make_pair(std::make_pair(left, top), + std::make_pair(right, bottom))}); + FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId + << ", <" << left << ", " << top << ", " << right << ", " + << bottom << "> } is succeed"; // if (screenRectMap_.find(flutterNodeId) == screenRectMap_.end()) { // screenRectMap_.insert( // {flutterNodeId, std::make_pair(std::make_pair(left, top), @@ -522,7 +522,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( int32_t top = static_cast(flutterNode.rect.fTop); int32_t right = static_cast(flutterNode.rect.fRight); int32_t bottom = static_cast(flutterNode.rect.fBottom); - ArkUI_AccessibleRect rect = {left, top, right, bottom}; + ArkUI_AccessibleRect rect = {left, top, right, bottom}; OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect); // 设置elementinfo的action类型 @@ -865,7 +865,8 @@ int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( } /** 将arkui的action类型转化为flutter的action类型 */ -flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions(ArkUI_Accessibility_ActionType arkui_action) { +flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( + ArkUI_Accessibility_ActionType arkui_action) { // 部分arkui操作和flutter操作的映射,其余action暂时无法适配, 这里先return 0 switch (arkui_action) { case ArkUI_Accessibility_ActionType:: @@ -912,15 +913,19 @@ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions(A return ACTIONS_::kSetText; default: - //TODO might not match to the valid action in arkui + // TODO might not match to the valid action in arkui return ACTIONS_::kDismiss; } } -void OhosAccessibilityBridge::DispatchSemanticsAction(int32_t id, flutter::SemanticsAction action, fml::MallocMapping args) { +void OhosAccessibilityBridge::DispatchSemanticsAction( + int32_t id, + flutter::SemanticsAction action, + fml::MallocMapping args) { FML_DLOG(INFO) << "DispatchSemanticsAction is called"; // TODO: ... 发送语义动作解析 - SHELL_HOLDER->GetPlatformView()->PlatformView::DispatchSemanticsAction(id, action, {}); + SHELL_HOLDER->GetPlatformView()->PlatformView::DispatchSemanticsAction( + id, action, {}); } /** @@ -942,182 +947,248 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } - //获取当前elementid对应的flutter语义节点 - auto flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); + // 获取当前elementid对应的flutter语义节点 + auto flutterNode = + getOrCreateFlutterSemanticsNode(static_cast(elementId)); // 根据当前elementid和无障碍动作类型,发送无障碍事件 - switch(action) { + switch (action) { /** Response to a click. 16 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: { - /** Click event, sent after the UI component responds. 1 */ - auto clickEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_CLICKED; + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: { + /** Click event, sent after the UI component responds. 1 */ + auto clickEventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_CLICKED; Flutter_SendAccessibilityAsyncEvent(elementId, clickEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: click("< action: click(" << action + << ")" << " event: click(" << clickEventType << ")"; - //解析arkui的屏幕点击 -> flutter对应节点的屏幕点击 - auto flutterTapAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), flutterTapAction, {}); + // 解析arkui的屏幕点击 -> flutter对应节点的屏幕点击 + auto flutterTapAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), flutterTapAction, + {}); break; } /** Response to a long click. 32 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: { + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: { /** Long click event, sent after the UI component responds. 2 */ - auto longClickEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_LONG_CLICKED; + auto longClickEventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_LONG_CLICKED; Flutter_SendAccessibilityAsyncEvent(elementId, longClickEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: longclick("< flutter对应节点的屏幕动作 - auto flutterLongPressAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), flutterLongPressAction, {}); + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: longclick(" + << action << ")" << " event: longclick(" + << longClickEventType << ")"; + + // 解析arkui的屏幕动作 -> flutter对应节点的屏幕动作 + auto flutterLongPressAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), + flutterLongPressAction, {}); break; } /** Accessibility focus acquisition. 64 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: { - //解析arkui的获焦 -> flutter对应节点的获焦 - auto flutterGainFocusAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), flutterGainFocusAction, {}); - - /** Accessibility focus event, sent after the UI component responds. 32768 */ - auto focusEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: { + // 解析arkui的获焦 -> flutter对应节点的获焦 + auto flutterGainFocusAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), + flutterGainFocusAction, {}); + + /** Accessibility focus event, sent after the UI component responds. 32768 + */ + auto focusEventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; Flutter_SendAccessibilityAsyncEvent(elementId, focusEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: focus("< action: focus(" << action + << ")" << " event: focus(" << focusEventType << ")"; + + if (flutterNode.HasAction(ACTIONS_::kIncrease) || + flutterNode.HasAction(ACTIONS_::kDecrease)) { + Flutter_SendAccessibilityAsyncEvent( + elementId, ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); } break; } /** Accessibility focus clearance. 128 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: { - //解析arkui的失焦 -> flutter对应节点的失焦 - auto flutterLoseFocusAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), flutterLoseFocusAction, {}); - - /** Accessibility focus cleared event, sent after the UI component responds. 65536 */ - auto clearFocusEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED; + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: { + // 解析arkui的失焦 -> flutter对应节点的失焦 + auto flutterLoseFocusAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), + flutterLoseFocusAction, {}); + + /** Accessibility focus cleared event, sent after the UI component + * responds. 65536 */ + auto clearFocusEventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED; Flutter_SendAccessibilityAsyncEvent(elementId, clearFocusEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: clearfocus("< action: clearfocus(" + << action << ")" << " event: clearfocus(" + << clearFocusEventType << ")"; break; } /** Forward scroll action. 256 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: { + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: { // flutter scroll forward with different situations if (flutterNode.HasAction(ACTIONS_::kScrollUp)) { - auto flutterScrollUpAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), flutterScrollUpAction, {}); + auto flutterScrollUpAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), + flutterScrollUpAction, {}); } else if (flutterNode.HasAction(ACTIONS_::kScrollLeft)) { - DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kScrollLeft, {}); + DispatchSemanticsAction(static_cast(elementId), + ACTIONS_::kScrollLeft, {}); } else if (flutterNode.HasAction(ACTIONS_::kIncrease)) { flutterNode.value = flutterNode.increasedValue; flutterNode.valueAttributes = flutterNode.increasedValueAttributes; - //TODO: Flutter_SendAccessibilityAsyncEvent() -> selected eventtype - Flutter_SendAccessibilityAsyncEvent(elementId, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); - DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kIncrease, {}); - - } else {} + // TODO: Flutter_SendAccessibilityAsyncEvent() -> selected eventtype + Flutter_SendAccessibilityAsyncEvent( + elementId, ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + DispatchSemanticsAction(static_cast(elementId), + ACTIONS_::kIncrease, {}); + + } else { + } - /** Scrolled event, sent when a scrollable component experiences a scroll event. 4096 */ - // ArkUI_AccessibilityEventType scrollEventType1 = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + /** Scrolled event, sent when a scrollable component experiences a scroll + * event. 4096 */ + // ArkUI_AccessibilityEventType scrollEventType1 = + // ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; // Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); - // FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: scroll forward("< action: scroll + // forward("<(elementId), flutterScrollDownAction, {}); + auto flutterScrollDownAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), + flutterScrollDownAction, {}); } else if (flutterNode.HasAction(ACTIONS_::kScrollRight)) { - DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kScrollRight, {}); + DispatchSemanticsAction(static_cast(elementId), + ACTIONS_::kScrollRight, {}); } else if (flutterNode.HasAction(ACTIONS_::kDecrease)) { flutterNode.value = flutterNode.decreasedValue; flutterNode.valueAttributes = flutterNode.decreasedValueAttributes; - //TODO: Flutter_SendAccessibilityAsyncEvent() -> selected eventtype - Flutter_SendAccessibilityAsyncEvent(elementId, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); - DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kDecrease, {}); - - } else {} + // TODO: Flutter_SendAccessibilityAsyncEvent() -> selected eventtype + Flutter_SendAccessibilityAsyncEvent( + elementId, ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + DispatchSemanticsAction(static_cast(elementId), + ACTIONS_::kDecrease, {}); + + } else { + } - /** Scrolled event, sent when a scrollable component experiences a scroll event. 4096 */ - // ArkUI_AccessibilityEventType scrollEventType2 = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + /** Scrolled event, sent when a scrollable component experiences a scroll + * event. 4096 */ + // ArkUI_AccessibilityEventType scrollEventType2 = + // ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; // Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType2); - // FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: scroll backward("< action: scroll + // backward("< action: copy("<(elementId), ACTIONS_::kCopy, {}); + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: copy(" << action + << ")"; + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCopy, + {}); break; } /** Paste action for text content. 2048 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: paste("<(elementId), ACTIONS_::kPaste, {}); + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE: { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: paste(" << action + << ")"; + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kPaste, + {}); break; } /** Cut action for text content. 4096 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: cut("<(elementId), ACTIONS_::kCut, {}); + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: cut(" << action + << ")"; + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCut, + {}); break; - /** Text selection action, requiring the setting of selectTextBegin, TextEnd, and TextInForward - * parameters to select a text segment in the text box. 8192 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: select text("<selectTextBegin, + * TextEnd, and TextInForward parameters to select a text + * segment in the text box. 8192 */ + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: select text(" + << action << ")"; + // TODO ...输入框文本选择操作 PerformSelectText(flutterNode, action, actionArguments); break; } /** Text content setting action. 16384 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: set text("< action: set text(" + << action << ")"; + // TODO ...输入框设置文本 PerformSetText(flutterNode, action, actionArguments); break; } /** Cursor position setting action. 1048576 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: set cursor position("< action: set cursor position(" + << action << ")"; + // TODO ...敬请期待 break; } /** Invalid action. 0 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID: { + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID: { /** Invalid event. 0 */ - ArkUI_AccessibilityEventType invalidEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_INVALID; + ArkUI_AccessibilityEventType invalidEventType = + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_INVALID; Flutter_SendAccessibilityAsyncEvent(elementId, invalidEventType); - FML_DLOG(ERROR) << "ExecuteAccessibilityAction -> action: invalid("< action: invalid(" + << action << ")" << " event: innvalid(" + << invalidEventType << ")"; break; } default: { /** custom semantics action */ - //TODO ...敬请期待 + // TODO ...敬请期待 } } - FML_DLOG(INFO) - << "--- ExecuteAccessibilityAction is end ---"; + FML_DLOG(INFO) << "--- ExecuteAccessibilityAction is end ---"; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; } @@ -1135,7 +1206,6 @@ int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( return 0; } - /** * 自定义无障碍异步事件发送 */ @@ -1155,9 +1225,12 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); FlutterNodeToElementInfoById(_elementInfo, elementId); - //若为获焦事件,则设置当前elementinfo获焦 - if(eventType == ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED) { - OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused(_elementInfo, true); + // 若为获焦事件,则设置当前elementinfo获焦 + if (eventType == + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED) { + OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused(_elementInfo, + true); } // 3.设置发送事件,如配置获焦、失焦、点击、滑动事件 @@ -1212,15 +1285,21 @@ bool OhosAccessibilityBridge::IsNodeFocusable( return !node.label.empty() || !node.value.empty() || !node.hint.empty(); } -void OhosAccessibilityBridge::PerformSetText(flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments) { - //TODO ... - // std::string key = ""; - // char* value; - //OH_ArkUI_FindAccessibilityActionArgumentByKey() +void OhosAccessibilityBridge::PerformSetText( + flutter::SemanticsNode flutterNode, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments) { + // TODO ... + // std::string key = ""; + // char* value; + // OH_ArkUI_FindAccessibilityActionArgumentByKey() } -void OhosAccessibilityBridge::PerformSelectText(flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments) { - //TODO... +void OhosAccessibilityBridge::PerformSelectText( + flutter::SemanticsNode flutterNode, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments) { + // TODO... } /** 获取当前flutter节点的组件类型,并映射为arkui组件 */ -- Gitee From 3cd1999a5c599b7f8b64d9711c6c53c084c682f6 Mon Sep 17 00:00:00 2001 From: zjxi Date: Sat, 21 Sep 2024 15:56:39 +0800 Subject: [PATCH 035/151] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9SetAbsoluteScreen?= =?UTF-8?q?Rect=E7=9A=84map=E5=AE=B9=E5=99=A8=E6=B7=BB=E5=8A=A0=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index b417a1e553..b93eaf7ff8 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -399,23 +399,17 @@ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, float top, float right, float bottom) { - screenRectMap_.insert( - {flutterNodeId, std::make_pair(std::make_pair(left, top), - std::make_pair(right, bottom))}); - FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId - << ", <" << left << ", " << top << ", " << right << ", " - << bottom << "> } is succeed"; - // if (screenRectMap_.find(flutterNodeId) == screenRectMap_.end()) { - // screenRectMap_.insert( - // {flutterNodeId, std::make_pair(std::make_pair(left, top), - // std::make_pair(right, bottom))}); - // FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId - // << ", <" << left << ", " << top << ", " << right << ", " - // << bottom << "> } is succeed"; - // } else { - // FML_DLOG(ERROR) << "SetAbsoluteScreenRect -> flutterNodeId=" - // << flutterNodeId << " already exists !"; - // } + + if (screenRectMap_.find(flutterNodeId) == screenRectMap_.end()) { + screenRectMap_[flutterNodeId] = std::make_pair(std::make_pair(left, top), + std::make_pair(right, bottom)); + FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId + << ", <" << left << ", " << top << ", " << right << ", " + << bottom << "> } is succeed"; + } else { + FML_DLOG(ERROR) << "SetAbsoluteScreenRect -> flutterNodeId=" + << flutterNodeId << " already exists !"; + } } std::pair, std::pair> -- Gitee From c4ba3af3defa805c3cbf31b88b7a2335b56bc63e Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 23 Sep 2024 11:19:03 +0800 Subject: [PATCH 036/151] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=B1=8F=E5=B9=95?= =?UTF-8?q?=E7=BB=9D=E5=AF=B9=E5=9D=90=E6=A0=87=E7=9A=84=E7=88=B6=E5=AD=90?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E5=BC=82=E5=B8=B8=E6=83=85=E5=86=B5=E5=88=A4?= =?UTF-8?q?=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos/accessibility/ohos_accessibility_bridge.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index b93eaf7ff8..59e91298f3 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -491,6 +491,12 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( FML_DLOG(INFO) << "ConvertChildRelativeRectToSceenRect -> { nodeId: " << currNode.id << ", (" << newLeft << ", " << newTop << ", " << newRight << ", " << newBottom << ")}"; + + if(newLeft < realParentLeft || newTop < realParentTop || newRight > realParentRight || newBottom > realParentBottom) { + FML_DLOG(ERROR) << "ConvertChildRelativeRectToSceenRect childRect is bigger than parentRect -> { nodeId: " + << currNode.id << ", (" << newLeft << ", " << newTop << ", " + << newRight << ", " << newBottom << ")}"; + } } /** @@ -518,6 +524,8 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( int32_t bottom = static_cast(flutterNode.rect.fBottom); ArkUI_AccessibleRect rect = {left, top, right, bottom}; OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect); + //设置root节点的屏幕绝对坐标rect + SetAbsoluteScreenRect(0, left, top, right, bottom); // 设置elementinfo的action类型 int32_t actionTypeNum = 2; @@ -680,9 +688,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( } // 设置无障碍播报文本 - std::string text = flutterNode.label.empty() - ? "当前节点id为" + std::to_string(flutterNode.id) - : flutterNode.label; + std::string text = flutterNode.label; OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfoFromList, text.c_str()); FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetAccessibilityText = " -- Gitee From 783d2a54289bb045ba21acd05e7ab413a91a7f8f Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 23 Sep 2024 15:50:34 +0800 Subject: [PATCH 037/151] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9flutter=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E7=9B=B8=E5=AF=B9=E5=9D=90=E6=A0=87=E8=BD=AC=E5=8C=96?= =?UTF-8?q?=E7=BB=9D=E5=AF=B9=E5=9D=90=E6=A0=87=E5=9C=A8=E5=BA=95=E9=83=A8?= =?UTF-8?q?=E5=AF=BC=E8=88=AA=E6=A0=8F=E5=A4=B1=E5=87=86bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 58 ++++++++++++------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 59e91298f3..dee7a4d5ab 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -21,7 +21,6 @@ #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/core/SkScalar.h" -#define SHELL_HOLDER (reinterpret_cast(nativeShellHolder_)) namespace flutter { OhosAccessibilityBridge OhosAccessibilityBridge::bridgeInstance; @@ -399,17 +398,21 @@ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, float top, float right, float bottom) { - - if (screenRectMap_.find(flutterNodeId) == screenRectMap_.end()) { - screenRectMap_[flutterNodeId] = std::make_pair(std::make_pair(left, top), - std::make_pair(right, bottom)); - FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId + screenRectMap_[flutterNodeId] = std::make_pair(std::make_pair(left, top), + std::make_pair(right, bottom)); + FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId << ", <" << left << ", " << top << ", " << right << ", " << bottom << "> } is succeed"; - } else { - FML_DLOG(ERROR) << "SetAbsoluteScreenRect -> flutterNodeId=" - << flutterNodeId << " already exists !"; - } + // if (screenRectMap_.find(flutterNodeId) == screenRectMap_.end()) { + // screenRectMap_[flutterNodeId] = std::make_pair(std::make_pair(left, top), + // std::make_pair(right, bottom)); + // FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId + // << ", <" << left << ", " << top << ", " << right << ", " + // << bottom << "> } is succeed"; + // } else { + // FML_DLOG(ERROR) << "SetAbsoluteScreenRect -> flutterNodeId=" + // << flutterNodeId << " already exists !"; + // } } std::pair, std::pair> @@ -481,10 +484,15 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( newBottom = realParentBottom; } else { // 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 - newLeft = (currLeft + _kMTransX) * realScaleFactor; - newTop = (currTop + _kMTransY) * realScaleFactor; - newRight = (currLeft + _kMTransX + currRight) * realScaleFactor; - newBottom = (currTop + _kMTransY + currBottom) * realScaleFactor; + // newLeft = (currLeft + _kMTransX) * realScaleFactor; + // newTop = (currTop + _kMTransY) * realScaleFactor; + // newRight = (currLeft + _kMTransX + currRight) * realScaleFactor; + // newBottom = (currTop + _kMTransY + currBottom) * realScaleFactor; + newLeft = (currLeft + _kMTransX) * realScaleFactor + realParentLeft; + newTop = (currTop + _kMTransY) * realScaleFactor + realParentTop; + newRight = (currLeft + _kMTransX + currRight) * realScaleFactor + realParentLeft; + newBottom = (currTop + _kMTransY + currBottom) * realScaleFactor + realParentTop; + } SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); } @@ -747,7 +755,6 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( /** * Called to obtain element information based on a specified node. * NOTE:该arkui接口需要在系统无障碍服务开启时,才能触发调用 - * TODO:当前实现版本为实现简易功能,正在完善实现实际使用场景逻辑并逐步优化 */ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( int64_t elementId, @@ -833,8 +840,10 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; } -/** Called to obtain element information based on a specified node and text - * content. */ +/** + * Called to obtain element information based on a specified node and text + * content. + */ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosByText( int64_t elementId, const char* text, @@ -918,14 +927,19 @@ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( } } +/** + * covert arkui-specific touch action to flutter-specific action + * and dispatch it from C++ to Dart + */ void OhosAccessibilityBridge::DispatchSemanticsAction( int32_t id, flutter::SemanticsAction action, fml::MallocMapping args) { - FML_DLOG(INFO) << "DispatchSemanticsAction is called"; - // TODO: ... 发送语义动作解析 - SHELL_HOLDER->GetPlatformView()->PlatformView::DispatchSemanticsAction( + auto ohos_shell_holder = reinterpret_cast(nativeShellHolder_); + ohos_shell_holder->GetPlatformView()->PlatformView::DispatchSemanticsAction( id, action, {}); + FML_DLOG(INFO) << "DispatchSemanticsAction -> shell_holder_id: "<(action); } /** @@ -1194,7 +1208,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( int32_t OhosAccessibilityBridge::ClearFocusedFocusAccessibilityNode() { // todo ... - FML_DLOG(INFO) << "=== ClearFocusedFocusAccessibilityNode is end"; + FML_DLOG(INFO) << "=== ClearFocusedFocusAccessibilityNode is end ==="; return 0; } int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( @@ -1202,7 +1216,7 @@ int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( int32_t requestId, int32_t* index) { // todo ... - FML_DLOG(INFO) << "=== GetAccessibilityNodeCursorPosition is end"; + FML_DLOG(INFO) << "=== GetAccessibilityNodeCursorPosition is end ==="; return 0; } -- Gitee From fedbd896c1d6c6e67e2eef57a236dca4012cc55a Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 23 Sep 2024 16:07:12 +0800 Subject: [PATCH 038/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0flutter=E8=AF=AD?= =?UTF-8?q?=E4=B9=89=E6=A0=91=E7=9B=B8=E5=85=B3=E7=BC=93=E5=AD=98=E5=AE=B9?= =?UTF-8?q?=E5=99=A8=E7=9A=84=E6=B8=85=E7=A9=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos/accessibility/ohos_accessibility_bridge.cpp | 12 ++++++++++++ .../ohos/accessibility/ohos_accessibility_bridge.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index dee7a4d5ab..7d10e65e75 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -1414,6 +1414,18 @@ void OhosAccessibilityBridge::removeSemanticsNode( } } +/** + * when the system accessibility service is shut down, + * clear all the flutter semantics-relevant caches like maps, vectors + */ +void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() { + flutterSemanticsTree_.clear(); + parentChildIdVec.clear(); + screenRectMap_.clear(); + actions_mp_.clear(); + flutterNavigationStack.clear(); +} + void OhosAccessibilityBridge::printTest(flutter::SemanticsNode node) { FML_DLOG(INFO) << "==================SemanticsNode====================="; SkMatrix _transform = node.transform.asM33(); diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index db38b8c919..97583f1b5b 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -76,6 +76,8 @@ class OhosAccessibilityBridge { std::pair, std::pair> GetAbsoluteScreenRect(int32_t flutterNodeId); void SetAbsoluteScreenRect(int32_t flutterNodeId, float left, float top, float right, float bottom); + void ClearFlutterSemanticsCaches(); + private: static OhosAccessibilityBridge bridgeInstance; -- Gitee From 854da2a79c840f16b0aa652c0f6f5fcb1e863dd2 Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 23 Sep 2024 17:14:32 +0800 Subject: [PATCH 039/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E8=B7=AF=E7=94=B1=E8=BD=AC=E6=8D=A2=E7=9A=84flutter?= =?UTF-8?q?=E8=AF=AD=E4=B9=89=E6=A0=91=E6=9B=B4=E6=96=B0=E7=AD=96=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 81 +++++++------------ .../accessibility/ohos_accessibility_bridge.h | 7 +- 2 files changed, 34 insertions(+), 54 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 7d10e65e75..186874eb04 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -40,55 +40,6 @@ void OhosAccessibilityBridge::updateSemantics( flutter::CustomAccessibilityActionUpdates actions) { FML_DLOG(INFO) << ("OhosAccessibilityBridge::updateSemantics is called"); - // 每次flutter语义节点更新,需要清空语义树容器节点信息 - // flutterSemanticsTree_.clear(); - // parentChildIdVec.clear(); - - std::set visitedObjs; - std::vector newRoutes; - - // Dispatch a TYPE_WINDOW_STATE_CHANGED event if the most recent route id - // changed from the - // previously cached route id. - // Finds the last route that is not in the previous routes. - // SEMANTICS_NODE_ lastAdded; - // lastAdded.id = -2; - // for (const auto& _node : newRoutes) { - // if (!flutterNavigationStack[_node.id]) { - // lastAdded = _node; - // } - // } - // // If all the routes are in the previous route, get the last route. - // if (lastAdded.id == -2 && newRoutes.size() > 0) { - // lastAdded = newRoutes[newRoutes.size() - 1]; - // } - - // There are two cases if lastAdded != nil - // 1. lastAdded is not in previous routes. In this case, - // lastAdded.id != previousRouteId - // 2. All new routes are in previous routes and - // lastAdded = newRoutes.last. - // In the first case, we need to announce new route. In the second case, - // we need to announce if one list is shorter than the other. - // if (lastAdded.id != -2 && (lastAdded.id != previousRouteId || - // newRoutes.size() != - // flutterNavigationStack.size())) { - // previousRouteId = lastAdded.id; - // onWindowNameChange(lastAdded); // todo - // } - // flutterNavigationStack.clear(); - // for (const auto& _node : newRoutes) { - // flutterNavigationStack.emplace_back(_node.id); - // } - - // for (const auto& item : flutterSemanticsTree_) { - // SEMANTICS_NODE_ obj = item.second; - // if (visitedObjs.find(obj) == visitedObjs.end()) { - // removeSemanticsNode(obj); - // flutterSemanticsTree_.erase(item.first); - // } - // } - /** 获取并分析每个语义节点的更新属性 */ for (auto& item : update) { // 获取当前更新的节点node @@ -1387,8 +1338,36 @@ flutter::SemanticsNode OhosAccessibilityBridge::getFlutterRootSemanticsNode() { return flutterSemanticsTree_.at(0); } +void OhosAccessibilityBridge::AddRouteNodes(std::vector edges, flutter::SemanticsNode node) { + if(node.HasFlag(FLAGS_::kScopesRoute)) { + edges.emplace_back(node); + } + for(auto& childNodeId: node.childrenInTraversalOrder) { + auto childNode = getOrCreateFlutterSemanticsNode(childNodeId); + AddRouteNodes(edges, childNode); + } +} + +std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) { + if(node.HasFlag(FLAGS_::kNamesRoute) && !node.label.empty()) { + return node.label; + } + for(auto& childNodeId: node.childrenInTraversalOrder) { + auto childNode = getOrCreateFlutterSemanticsNode(childNodeId); + std::string newName = GetRouteName(childNode); + if(!newName.empty()) { + return newName; + } + } + return ""; +} + void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { - // todo ... + std::string routeName = GetRouteName(route); + if(routeName.empty()) { + routeName = " "; + } + Flutter_SendAccessibilityAsyncEvent(static_cast(route.id), ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); } void OhosAccessibilityBridge::removeSemanticsNode( @@ -1423,7 +1402,7 @@ void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() { parentChildIdVec.clear(); screenRectMap_.clear(); actions_mp_.clear(); - flutterNavigationStack.clear(); + flutterNavigationVec_.clear(); } void OhosAccessibilityBridge::printTest(flutter::SemanticsNode node) { diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 97583f1b5b..3cb8eddaae 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -33,7 +33,7 @@ namespace flutter { typedef flutter::SemanticsFlags FLAGS_; typedef flutter::SemanticsAction ACTIONS_; -typedef flutter::SemanticsNode SEMANTICS_NODE_; +typedef flutter::SemanticsNode FLUTTER_NODE_; /** * flutter和ohos的无障碍服务桥接 @@ -86,7 +86,7 @@ class OhosAccessibilityBridge { std::unordered_map flutterSemanticsTree_; std::unordered_map, std::pair>> screenRectMap_; std::unordered_map actions_mp_; - std::vector flutterNavigationStack; + std::vector flutterNavigationVec_; static const int32_t ROOT_NODE_ID = 0; @@ -100,7 +100,8 @@ class OhosAccessibilityBridge { void PerformSetText(flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments); void PerformSelectText(flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments); - + void AddRouteNodes(std::vector edges, flutter::SemanticsNode node); + std::string GetRouteName(flutter::SemanticsNode node); void onWindowNameChange(flutter::SemanticsNode route); void removeSemanticsNode(flutter::SemanticsNode nodeToBeRemoved); -- Gitee From a58ee8c4fbc347c2819c18a972dded82bec0d9fc Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 23 Sep 2024 17:20:39 +0800 Subject: [PATCH 040/151] =?UTF-8?q?fix:=E5=AE=8C=E5=96=84exectute=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E7=9A=84=E5=85=B3=E4=BA=8Elistview=E5=8E=9F=E7=94=9F?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E7=9A=84=E6=BB=91=E5=8A=A8=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 186874eb04..11d5cceeff 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -451,7 +451,8 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( << currNode.id << ", (" << newLeft << ", " << newTop << ", " << newRight << ", " << newBottom << ")}"; - if(newLeft < realParentLeft || newTop < realParentTop || newRight > realParentRight || newBottom > realParentBottom) { + if(newLeft < realParentLeft || newTop < realParentTop || newRight > realParentRight || newBottom > realParentBottom + || newLeft >= newRight || newTop >= newBottom) { FML_DLOG(ERROR) << "ConvertChildRelativeRectToSceenRect childRect is bigger than parentRect -> { nodeId: " << currNode.id << ", (" << newLeft << ", " << newTop << ", " << newRight << ", " << newBottom << ")}"; @@ -1023,15 +1024,17 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( } else { } - - /** Scrolled event, sent when a scrollable component experiences a scroll - * event. 4096 */ - // ArkUI_AccessibilityEventType scrollEventType1 = - // ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; - // Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); - // FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: scroll - // forward("< action: scroll + forward("< action: scroll - // backward("< action: scroll + backward("< Date: Mon, 23 Sep 2024 19:37:29 +0800 Subject: [PATCH 041/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E5=BD=93?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E6=97=A0=E9=9A=9C=E7=A2=8D=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E6=97=B6=E6=B8=85=E7=90=86bridge=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E8=AF=AD=E4=B9=89=E6=A0=91=E7=9B=B8=E5=85=B3=E7=BC=93?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 94 +++++++++++++------ .../accessibility/ohos_accessibility_bridge.h | 3 + .../ohos/napi/platform_view_ohos_napi.cpp | 8 ++ 3 files changed, 74 insertions(+), 31 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 11d5cceeff..55095155d0 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -14,6 +14,7 @@ */ #include "ohos_accessibility_bridge.h" #include +#include #include "flutter/fml/logging.h" #include "flutter/shell/common/platform_view.h" #include "flutter/shell/platform/embedder/embedder.h" @@ -72,6 +73,57 @@ void OhosAccessibilityBridge::updateSemantics( << ", " << node.childrenInTraversalOrder[i] << ")"; } + // 判断是否触发滑动操作 + if (IsNodeScrollable(node)) { + double nodePosition = node.scrollPosition; + double nodeScrollExtentMax = node.scrollExtentMax; + double nodeScrollExtentMin = node.scrollExtentMin; + double infinity = std::numeric_limits::infinity(); + //设置flutter可滑动的最大范围值 + if(nodeScrollExtentMax == infinity) { + nodeScrollExtentMax = SCROLL_EXTENT_FOR_INFINITY; + if(nodePosition > SCROLL_POSITION_CAP_FOR_INFINITY) { + nodePosition = SCROLL_POSITION_CAP_FOR_INFINITY; + } + } + if (nodeScrollExtentMin == infinity) { + nodeScrollExtentMax += SCROLL_EXTENT_FOR_INFINITY; + if (nodePosition < -SCROLL_POSITION_CAP_FOR_INFINITY) { + nodePosition = -SCROLL_POSITION_CAP_FOR_INFINITY; + } + nodePosition += SCROLL_EXTENT_FOR_INFINITY; + } else { + nodeScrollExtentMax -= node.scrollExtentMin; + nodePosition -= node.scrollExtentMin; + } + + if (node.HasAction(ACTIONS_::kScrollUp) || node.HasAction(ACTIONS_::kScrollDown)) { + //TODO: ohos/arkui未提供相应的滑动属性配置event + // event.setScrollY((int) nodePosition); + // event.setMaxScrollY((int) nodeScrollExtentMax); + } else if (node.HasAction(ACTIONS_::kScrollLeft) || node.HasAction(ACTIONS_::kScrollRight)) { + //TODO: ohos/arkui未提供相应的滑动属性配置event + // event.setScrollX((int) nodePosition); + // event.setMaxScrollX((int) nodeScrollExtentMax); + } + if (node.scrollChildren > 0) { + // We don't need to add 1 to the scroll index because TalkBack does this automagically. + // event.setItemCount(object.scrollChildren); + // event.setFromIndex(object.scrollIndex); + int visibleChildren = 0; + // handle hidden children at the beginning and end of the list. + for (const auto& childId : node.childrenInHitTestOrder) { + auto childNode = getOrCreateFlutterSemanticsNode(childId); + if (!childNode.HasFlag(FLAGS_::kIsHidden)) { + visibleChildren += 1; + } + } + //TODO: 缺少ohos/arkui的滑动事件配置事件接口 + //event.setToIndex(object.scrollIndex + visibleChildren - 1); + } + // sendAccessibilityEvent(event) + } + // TODO: 若该对象是输入焦点节点,且发生更新变化,则发送给os有关它的信息 // std::shared_ptr // inputFocusedSemanticsNode; // 当前输入焦点节点 @@ -132,31 +184,6 @@ void OhosAccessibilityBridge::updateSemantics( // } // } - // todo: 是否触发滑动操作 - bool didScroll = true; - if (didScroll) { - // 1. 声明并创建accessibilityEvent类型,比如滑动事件 - // 2. - // 获取semanticsNode里scrollPosition、scrollExtensionMax、scrollExtensionMin字段 - // 3. 发送事件中包含上述scroll位置变动信息(如下所示) - // int32_t scrollChildren = 0; - // int32_t scrollIndex = 0; - // double scrollPosition = std::nan(""); - // double scrollExtentMax = std::nan(""); - // double scrollExtentMin = std::nan(""); - int32_t scrollChildren = 0; - if (scrollChildren > 0) { - // todo 发送事件,包含scrollChildren数量、scrollIndex - // int visibleChildren = 0; - // // handle hidden children at the beginning and end of the list. - // for (flutter::SemanticsNode child : node.childrenInHitTestOrder) { - // if (!child.hasFlag(Flag.IS_HIDDEN)) { - // visibleChildren += 1; - // } - // } - } - // sendAccessibilityEvent(event) - } // 判断是否触发liveRegion活动区,当前节点是否活跃(优先级低) if (node.HasFlag(FLAGS_::kIsLiveRegion)) { @@ -184,6 +211,15 @@ void OhosAccessibilityBridge::updateSemantics( FML_DLOG(INFO) << "=== UpdateSemantics is end ==="; } +bool OhosAccessibilityBridge::IsNodeScrollable(flutter::SemanticsNode flutterNode) { + // int32_t scrollChildren = 0; + // int32_t scrollIndex = 0; + // double scrollPosition = std::nan(""); + // double scrollExtentMax = std::nan(""); + // double scrollExtentMin = std::nan(""); + return flutterNode.scrollPosition != std::nan(""); +} + void OhosAccessibilityBridge::announce(std::unique_ptr& message) { // 创建并设置屏幕朗读事件 ArkUI_AccessibilityEventInfo* announceEventInfo = @@ -1031,9 +1067,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( ArkUI_AccessibilityEventType scrollEventType1 = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: scroll - forward("< action: scroll forward("< action: scroll - backward("< action: scroll backward("< flutterNavigationVec_; static const int32_t ROOT_NODE_ID = 0; + constexpr static const double SCROLL_EXTENT_FOR_INFINITY = 100000.0; + constexpr static const double SCROLL_POSITION_CAP_FOR_INFINITY = 70000.0; void FlutterTreeToArkuiTree(ArkUI_AccessibilityElementInfoList* elementInfoList); @@ -97,6 +99,7 @@ class OhosAccessibilityBridge { std::string GetNodeComponentType(const flutter::SemanticsNode& node); flutter::SemanticsAction ArkuiActionsToFlutterActions(ArkUI_Accessibility_ActionType arkui_action); + bool IsNodeScrollable(flutter::SemanticsNode flutterNode); void PerformSetText(flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments); void PerformSelectText(flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments); diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index 8465711624..8992f8b660 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1926,6 +1926,14 @@ napi_value PlatformViewOHOSNapi::nativeSetSemanticsEnabled(napi_env env, napi_ca FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeSetSemanticsEnabled " "OHOS_SHELL_HOLDER->GetPlatformView()->SetSemanticsEnabled= "<ClearFlutterSemanticsCaches(); + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeSetSemanticsEnabled -> ClearFlutterSemanticsCaches()"; + } + //给无障碍bridge传递nativeShellHolderId auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge->nativeShellHolder_ = shell_holder; -- Gitee From 0578735d8f69a36e477cbd29ca6f670103c01441 Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 23 Sep 2024 19:38:41 +0800 Subject: [PATCH 042/151] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- shell/platform/ohos/napi/platform_view_ohos_napi.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index 8992f8b660..9ee4b82542 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1928,7 +1928,6 @@ napi_value PlatformViewOHOSNapi::nativeSetSemanticsEnabled(napi_env env, napi_ca // when the system accessibility service is off if(!enabled) { - //给无障碍bridge传递nativeShellHolderId auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge->ClearFlutterSemanticsCaches(); FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeSetSemanticsEnabled -> ClearFlutterSemanticsCaches()"; -- Gitee From 8e007df4d3dbac4ab59c3c3c9cb3e0d3ac0ae555 Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 25 Sep 2024 21:30:21 +0800 Subject: [PATCH 043/151] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E5=B1=9E=E6=80=A7=E8=AE=BE=E7=BD=AE=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E5=92=8C=E6=9C=97=E8=AF=BB=E9=83=A8=E5=88=86bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 326 +++++++++++++----- .../accessibility/ohos_accessibility_bridge.h | 11 +- 2 files changed, 251 insertions(+), 86 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 55095155d0..7f8b6efec4 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -13,8 +13,8 @@ * limitations under the License. */ #include "ohos_accessibility_bridge.h" -#include #include +#include #include "flutter/fml/logging.h" #include "flutter/shell/common/platform_view.h" #include "flutter/shell/platform/embedder/embedder.h" @@ -45,7 +45,10 @@ void OhosAccessibilityBridge::updateSemantics( for (auto& item : update) { // 获取当前更新的节点node const flutter::SemanticsNode& node = item.second; - printTest(node); // print node info for debugging + + // print semantics node and flags info for debugging + GetSemanticsNodeDebugInfo(node); + GetSemanticsFlagsDebugInfo(node); /** * 构建flutter无障碍语义节点树 @@ -79,10 +82,10 @@ void OhosAccessibilityBridge::updateSemantics( double nodeScrollExtentMax = node.scrollExtentMax; double nodeScrollExtentMin = node.scrollExtentMin; double infinity = std::numeric_limits::infinity(); - //设置flutter可滑动的最大范围值 - if(nodeScrollExtentMax == infinity) { + // 设置flutter可滑动的最大范围值 + if (nodeScrollExtentMax == infinity) { nodeScrollExtentMax = SCROLL_EXTENT_FOR_INFINITY; - if(nodePosition > SCROLL_POSITION_CAP_FOR_INFINITY) { + if (nodePosition > SCROLL_POSITION_CAP_FOR_INFINITY) { nodePosition = SCROLL_POSITION_CAP_FOR_INFINITY; } } @@ -97,18 +100,20 @@ void OhosAccessibilityBridge::updateSemantics( nodePosition -= node.scrollExtentMin; } - if (node.HasAction(ACTIONS_::kScrollUp) || node.HasAction(ACTIONS_::kScrollDown)) { - //TODO: ohos/arkui未提供相应的滑动属性配置event - // event.setScrollY((int) nodePosition); - // event.setMaxScrollY((int) nodeScrollExtentMax); - } else if (node.HasAction(ACTIONS_::kScrollLeft) || node.HasAction(ACTIONS_::kScrollRight)) { - //TODO: ohos/arkui未提供相应的滑动属性配置event - // event.setScrollX((int) nodePosition); - // event.setMaxScrollX((int) nodeScrollExtentMax); + if (node.HasAction(ACTIONS_::kScrollUp) || + node.HasAction(ACTIONS_::kScrollDown)) { + // TODO: ohos/arkui未提供相应的滑动属性配置event + // event.setScrollY((int) nodePosition); + // event.setMaxScrollY((int) nodeScrollExtentMax); + } else if (node.HasAction(ACTIONS_::kScrollLeft) || + node.HasAction(ACTIONS_::kScrollRight)) { + // TODO: ohos/arkui未提供相应的滑动属性配置event + // event.setScrollX((int) nodePosition); + // event.setMaxScrollX((int) nodeScrollExtentMax); } if (node.scrollChildren > 0) { - // We don't need to add 1 to the scroll index because TalkBack does this automagically. - // event.setItemCount(object.scrollChildren); + // We don't need to add 1 to the scroll index because TalkBack does this + // automagically. event.setItemCount(object.scrollChildren); // event.setFromIndex(object.scrollIndex); int visibleChildren = 0; // handle hidden children at the beginning and end of the list. @@ -118,8 +123,8 @@ void OhosAccessibilityBridge::updateSemantics( visibleChildren += 1; } } - //TODO: 缺少ohos/arkui的滑动事件配置事件接口 - //event.setToIndex(object.scrollIndex + visibleChildren - 1); + // TODO: 缺少ohos/arkui的滑动事件配置事件接口 + // event.setToIndex(object.scrollIndex + visibleChildren - 1); } // sendAccessibilityEvent(event) } @@ -184,7 +189,6 @@ void OhosAccessibilityBridge::updateSemantics( // } // } - // 判断是否触发liveRegion活动区,当前节点是否活跃(优先级低) if (node.HasFlag(FLAGS_::kIsLiveRegion)) { // TODO: ... @@ -194,7 +198,7 @@ void OhosAccessibilityBridge::updateSemantics( // TODO: 遍历更新的actions,并将所有的actions的id添加进actionMap for (const auto& item : actions) { const flutter::CustomAccessibilityAction action = item.second; - printTestActions(action); + GetCustomActionDebugInfo(action); actions_mp_[action.id] = action; } @@ -211,7 +215,8 @@ void OhosAccessibilityBridge::updateSemantics( FML_DLOG(INFO) << "=== UpdateSemantics is end ==="; } -bool OhosAccessibilityBridge::IsNodeScrollable(flutter::SemanticsNode flutterNode) { +bool OhosAccessibilityBridge::IsNodeScrollable( + flutter::SemanticsNode flutterNode) { // int32_t scrollChildren = 0; // int32_t scrollIndex = 0; // double scrollPosition = std::nan(""); @@ -385,11 +390,11 @@ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, float top, float right, float bottom) { - screenRectMap_[flutterNodeId] = std::make_pair(std::make_pair(left, top), - std::make_pair(right, bottom)); + screenRectMap_[flutterNodeId] = + std::make_pair(std::make_pair(left, top), std::make_pair(right, bottom)); FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId - << ", <" << left << ", " << top << ", " << right << ", " - << bottom << "> } is succeed"; + << ", <" << left << ", " << top << ", " << right << ", " + << bottom << "> } is succeed"; // if (screenRectMap_.find(flutterNodeId) == screenRectMap_.end()) { // screenRectMap_[flutterNodeId] = std::make_pair(std::make_pair(left, top), // std::make_pair(right, bottom)); @@ -477,9 +482,10 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( // newBottom = (currTop + _kMTransY + currBottom) * realScaleFactor; newLeft = (currLeft + _kMTransX) * realScaleFactor + realParentLeft; newTop = (currTop + _kMTransY) * realScaleFactor + realParentTop; - newRight = (currLeft + _kMTransX + currRight) * realScaleFactor + realParentLeft; - newBottom = (currTop + _kMTransY + currBottom) * realScaleFactor + realParentTop; - + newRight = + (currLeft + _kMTransX + currRight) * realScaleFactor + realParentLeft; + newBottom = + (currTop + _kMTransY + currBottom) * realScaleFactor + realParentTop; } SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); } @@ -487,11 +493,13 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( << currNode.id << ", (" << newLeft << ", " << newTop << ", " << newRight << ", " << newBottom << ")}"; - if(newLeft < realParentLeft || newTop < realParentTop || newRight > realParentRight || newBottom > realParentBottom - || newLeft >= newRight || newTop >= newBottom) { - FML_DLOG(ERROR) << "ConvertChildRelativeRectToSceenRect childRect is bigger than parentRect -> { nodeId: " - << currNode.id << ", (" << newLeft << ", " << newTop << ", " - << newRight << ", " << newBottom << ")}"; + if (newLeft < realParentLeft || newTop < realParentTop || + newRight > realParentRight || newBottom > realParentBottom || + newLeft >= newRight || newTop >= newBottom) { + FML_DLOG(ERROR) << "ConvertChildRelativeRectToSceenRect childRect is " + "bigger than parentRect -> { nodeId: " + << currNode.id << ", (" << newLeft << ", " << newTop << ", " + << newRight << ", " << newBottom << ")}"; } } @@ -520,7 +528,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( int32_t bottom = static_cast(flutterNode.rect.fBottom); ArkUI_AccessibleRect rect = {left, top, right, bottom}; OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect); - //设置root节点的屏幕绝对坐标rect + // 设置root节点的屏幕绝对坐标rect SetAbsoluteScreenRect(0, left, top, right, bottom); // 设置elementinfo的action类型 @@ -581,10 +589,6 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( FML_DLOG(INFO) << "FlutterNodeToElementInfoById elementId = " << elementId; flutter::SemanticsNode flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); - // 获取当前节点的组件类型 - std::string componentTypeName = GetNodeComponentType(flutterNode); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById componentTypeName = " - << componentTypeName; // flutter父子节点相对坐标位置的矩阵变换,转化为绝对屏幕坐标 ConvertChildRelativeRectToSceenRect(flutterNode); @@ -689,6 +693,8 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( text.c_str()); FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetAccessibilityText = " << text; + std::string hint = flutterNode.hint; + OH_ArkUI_AccessibilityElementInfoSetHintText(elementInfoFromList, hint.c_str()); // 配置child节点信息 int32_t childCount = @@ -704,17 +710,52 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds); - // 配置常用属性 + /** + * 根据当前flutter节点的SemanticsFlags特性,配置对应的elementinfo属性 + */ + //判断当前节点是否可点击 + if(IsNodeClickable(flutterNode)) { + OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); + FML_DLOG(INFO) <<"flutterNode.id="< true"; + } + //判断当前节点是否可获焦点 if (IsNodeFocusable(flutterNode)) { OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true); + FML_DLOG(INFO) <<"flutterNode.id="< true"; + } + //判断当前节点是否为密码输入框 + if(IsNodePassword(flutterNode)) { + OH_ArkUI_AccessibilityElementInfoSetIsPassword(elementInfoFromList, true); + FML_DLOG(INFO) <<"flutterNode.id="< true"; } - OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); - OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true); - OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true); - OH_ArkUI_AccessibilityElementInfoSetSelected(elementInfoFromList, true); + //判断当前节点是否具备checkable状态 (如:checkbox, radio button) + if(IsNodeCheckable(flutterNode)) { + OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true); + FML_DLOG(INFO) <<"flutterNode.id="< true"; + } + //判断当前节点(check box/radio button)是否checked/unchecked + if(IsNodeChecked(flutterNode)) { + OH_ArkUI_AccessibilityElementInfoSetChecked(elementInfoFromList, true); + FML_DLOG(INFO) <<"flutterNode.id="< true"; + } + //判断当前节点组件是否可显示 + if(IsNodeVisible(flutterNode)) { + OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true); + FML_DLOG(INFO) <<"flutterNode.id="< true"; + } + //判断当前节点组件是否选中 + if(IsNodeSelected(flutterNode)) { + OH_ArkUI_AccessibilityElementInfoSetSelected(elementInfoFromList, true); + FML_DLOG(INFO) <<"flutterNode.id="< true"; + } + //当前节点组件默认enabled OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true); - // FIXME: 元素所属的组件类型(如:root, button,text等) + // 获取当前节点的组件类型 + std::string componentTypeName = GetNodeComponentType(flutterNode); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById componentTypeName = " + << componentTypeName; + //flutter节点对应elementinfo所属的组件类型(如:root, button,text等) if (elementId == 0) { OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root"); @@ -737,8 +778,57 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, false); FML_DLOG(INFO) - << "OhosAccessibilityBridge::FlutterNodeToElementInfoById is end"; + << "=== OhosAccessibilityBridge::FlutterNodeToElementInfoById is end ==="; +} + +/** + * 判断当前flutter节点组件是否可点击 + */ +bool OhosAccessibilityBridge::IsNodeClickable(flutter::SemanticsNode flutterNode) { + return flutterNode.HasFlag(FLAGS_::kHasCheckedState) + || flutterNode.HasFlag(FLAGS_::kIsButton) + || flutterNode.HasFlag(FLAGS_::kIsTextField) + || flutterNode.HasFlag(FLAGS_::kIsImage) + || flutterNode.HasFlag(FLAGS_::kIsHeader) + || flutterNode.HasFlag(FLAGS_::kIsLiveRegion) + || flutterNode.HasFlag(FLAGS_::kIsMultiline) + || flutterNode.HasFlag(FLAGS_::kIsLink) + || flutterNode.HasFlag(FLAGS_::kIsSlider) + || flutterNode.HasFlag(FLAGS_::kIsKeyboardKey) + || flutterNode.HasFlag(FLAGS_::kHasToggledState) + || flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); } +/** + * 判断当前flutter节点组件是否可显示 + */ +bool OhosAccessibilityBridge::IsNodeVisible(flutter::SemanticsNode flutterNode) { + return flutterNode.HasFlag(FLAGS_::kIsHidden) ? false : true; +} +/** + * 判断当前flutter节点组件是否具备checkable属性 + */ +bool OhosAccessibilityBridge::IsNodeCheckable(flutter::SemanticsNode flutterNode) { + return flutterNode.HasFlag(FLAGS_::kHasCheckedState); +} +/** + * 判断当前flutter节点组件是否checked/unchecked(checkbox、radio button) + */ +bool OhosAccessibilityBridge::IsNodeChecked(flutter::SemanticsNode flutterNode) { + return flutterNode.HasFlag(FLAGS_::kIsChecked); +} +/** + * 判断当前flutter节点组件是否选中 + */ +bool OhosAccessibilityBridge::IsNodeSelected(flutter::SemanticsNode flutterNode) { + return flutterNode.HasFlag(FLAGS_::kIsSelected); +} +/** + * 判断当前flutter节点组件是否为密码输入框 + */ +bool OhosAccessibilityBridge::IsNodePassword(flutter::SemanticsNode flutterNode) { + return flutterNode.HasFlag(FLAGS_::kIsTextField) && flutterNode.HasFlag(FLAGS_::kIsObscured); +} + /** * Called to obtain element information based on a specified node. @@ -828,9 +918,9 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; } -/** +/** * Called to obtain element information based on a specified node and text - * content. + * content. */ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosByText( int64_t elementId, @@ -917,17 +1007,19 @@ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( /** * covert arkui-specific touch action to flutter-specific action - * and dispatch it from C++ to Dart + * and dispatch it from C++ to Dart */ void OhosAccessibilityBridge::DispatchSemanticsAction( int32_t id, flutter::SemanticsAction action, fml::MallocMapping args) { - auto ohos_shell_holder = reinterpret_cast(nativeShellHolder_); + auto ohos_shell_holder = + reinterpret_cast(nativeShellHolder_); ohos_shell_holder->GetPlatformView()->PlatformView::DispatchSemanticsAction( id, action, {}); - FML_DLOG(INFO) << "DispatchSemanticsAction -> shell_holder_id: "<(action); + FML_DLOG(INFO) << "DispatchSemanticsAction -> shell_holder_id: " + << nativeShellHolder_ << " id: " << id + << " action: " << static_cast(action); } /** @@ -1060,14 +1152,17 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( } else { } - std::string currComponetType = GetNodeComponentType(flutterNode); - if(currComponetType == "ListView") { - /** Scrolled event, sent when a scrollable component experiences a scroll - * event. 4096 */ + std::string currComponetType = GetNodeComponentType(flutterNode); + if (currComponetType == "ListView") { + /** Scrolled event, sent when a scrollable component experiences a + * scroll event. 4096 */ ArkUI_AccessibilityEventType scrollEventType1 = - ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: scroll forward("< action: scroll forward(" << action + << ")" << " event: scroll forward(" << scrollEventType1 << ")"; } break; } @@ -1097,14 +1192,18 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( } else { } - std::string currComponetType = GetNodeComponentType(flutterNode); - if(currComponetType == "ListView") { - /** Scrolled event, sent when a scrollable component experiences a scroll - * event. 4096 */ + std::string currComponetType = GetNodeComponentType(flutterNode); + if (currComponetType == "ListView") { + /** Scrolled event, sent when a scrollable component experiences a + * scroll event. 4096 */ ArkUI_AccessibilityEventType scrollEventType2 = - ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType2); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: scroll backward("< action: scroll backward(" + << action << ")" << " event: scroll backward(" << scrollEventType2 + << ")"; } break; } @@ -1340,8 +1439,8 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( if (node.HasFlag(FLAGS_::kHasCheckedState)) { if (node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup)) { - // arkui没有RadioButton,这里透传为Radio - return "Radio"; + // arkui没有RadioButton,这里透传为RadioButton + return "RadioButton"; } else { return "Checkbox"; } @@ -1349,11 +1448,10 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( if (node.HasFlag(FLAGS_::kHasToggledState)) { // arkui没有ToggleSwitch,这里透传为Toggle - return "Toggle"; + return "ToggleSwitch"; } - if ((!node.label.empty() || !node.tooltip.empty() || !node.hint.empty()) && - node.id != 0) { + if ((!node.label.empty() || !node.tooltip.empty() || !node.hint.empty())) { return "Text"; } @@ -1375,24 +1473,26 @@ flutter::SemanticsNode OhosAccessibilityBridge::getFlutterRootSemanticsNode() { return flutterSemanticsTree_.at(0); } -void OhosAccessibilityBridge::AddRouteNodes(std::vector edges, flutter::SemanticsNode node) { - if(node.HasFlag(FLAGS_::kScopesRoute)) { +void OhosAccessibilityBridge::AddRouteNodes( + std::vector edges, + flutter::SemanticsNode node) { + if (node.HasFlag(FLAGS_::kScopesRoute)) { edges.emplace_back(node); } - for(auto& childNodeId: node.childrenInTraversalOrder) { + for (auto& childNodeId : node.childrenInTraversalOrder) { auto childNode = getOrCreateFlutterSemanticsNode(childNodeId); AddRouteNodes(edges, childNode); } } std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) { - if(node.HasFlag(FLAGS_::kNamesRoute) && !node.label.empty()) { + if (node.HasFlag(FLAGS_::kNamesRoute) && !node.label.empty()) { return node.label; } - for(auto& childNodeId: node.childrenInTraversalOrder) { + for (auto& childNodeId : node.childrenInTraversalOrder) { auto childNode = getOrCreateFlutterSemanticsNode(childNodeId); std::string newName = GetRouteName(childNode); - if(!newName.empty()) { + if (!newName.empty()) { return newName; } } @@ -1401,10 +1501,13 @@ std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) { void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { std::string routeName = GetRouteName(route); - if(routeName.empty()) { + if (routeName.empty()) { routeName = " "; } - Flutter_SendAccessibilityAsyncEvent(static_cast(route.id), ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); + Flutter_SendAccessibilityAsyncEvent( + static_cast(route.id), + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); } void OhosAccessibilityBridge::removeSemanticsNode( @@ -1432,7 +1535,7 @@ void OhosAccessibilityBridge::removeSemanticsNode( /** * when the system accessibility service is shut down, - * clear all the flutter semantics-relevant caches like maps, vectors + * clear all the flutter semantics-relevant caches like maps, vectors */ void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() { flutterSemanticsTree_.clear(); @@ -1442,8 +1545,8 @@ void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() { flutterNavigationVec_.clear(); } -void OhosAccessibilityBridge::printTest(flutter::SemanticsNode node) { - FML_DLOG(INFO) << "==================SemanticsNode====================="; +void OhosAccessibilityBridge::GetSemanticsNodeDebugInfo(flutter::SemanticsNode node) { + FML_DLOG(INFO) << "-------------------SemanticsNode------------------"; SkMatrix _transform = node.transform.asM33(); FML_DLOG(INFO) << "node.id=" << node.id; FML_DLOG(INFO) << "node.label=" << node.label; @@ -1494,26 +1597,81 @@ void OhosAccessibilityBridge::printTest(flutter::SemanticsNode node) { FML_DLOG(INFO) << "node.childrenInTraversalOrder[" << i << "]=" << node.childrenInTraversalOrder[i]; } - FML_DLOG(INFO) << "node.childrenInHitTestOrder.size()=" << node.childrenInHitTestOrder.size(); for (uint32_t i = 0; i < node.childrenInHitTestOrder.size(); i++) { FML_DLOG(INFO) << "node.childrenInHitTestOrder[" << i << "]=" << node.childrenInHitTestOrder[i]; } - FML_DLOG(INFO) << "node.customAccessibilityActions.size()=" << node.customAccessibilityActions.size(); for (uint32_t i = 0; i < node.customAccessibilityActions.size(); i++) { FML_DLOG(INFO) << "node.customAccessibilityActions[" << i << "]=" << node.customAccessibilityActions[i]; } - FML_DLOG(INFO) << "=================SemanticsNode======================"; + FML_DLOG(INFO) << "------------------SemanticsNode-----------------"; +} + +void OhosAccessibilityBridge::GetSemanticsFlagsDebugInfo(flutter::SemanticsNode node) { + FML_DLOG(INFO) << "----------------SemanticsFlags-------------------------"; + FML_DLOG(INFO) << "kHasCheckedState: " + << node.HasFlag(FLAGS_::kHasCheckedState); + FML_DLOG(INFO) << "kIsChecked:" + << node.HasFlag(FLAGS_::kIsChecked); + FML_DLOG(INFO) << "kIsSelected:" + << node.HasFlag(FLAGS_::kIsSelected); + FML_DLOG(INFO) << "kIsButton:" + << node.HasFlag(FLAGS_::kIsButton); + FML_DLOG(INFO) << "kIsTextField:" + << node.HasFlag(FLAGS_::kIsTextField); + FML_DLOG(INFO) << "kIsFocused:" + << node.HasFlag(FLAGS_::kIsFocused); + FML_DLOG(INFO) << "kHasEnabledState:" + << node.HasFlag(FLAGS_::kHasEnabledState); + FML_DLOG(INFO) << "kIsEnabled:" + << node.HasFlag(FLAGS_::kIsEnabled); + FML_DLOG(INFO) << "kIsInMutuallyExclusiveGroup:" + << node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup); + FML_DLOG(INFO) << "kIsHeader:" + << node.HasFlag(FLAGS_::kIsHeader); + FML_DLOG(INFO) << "kIsObscured:" + << node.HasFlag(FLAGS_::kIsObscured); + FML_DLOG(INFO) << "kScopesRoute:" + << node.HasFlag(FLAGS_::kScopesRoute); + FML_DLOG(INFO) << "kNamesRoute:" + << node.HasFlag(FLAGS_::kNamesRoute); + FML_DLOG(INFO) << "kIsHidden:" + << node.HasFlag(FLAGS_::kIsHidden); + FML_DLOG(INFO) << "kIsImage:" + << node.HasFlag(FLAGS_::kIsImage); + FML_DLOG(INFO) << "kIsLiveRegion:" + << node.HasFlag(FLAGS_::kIsLiveRegion); + FML_DLOG(INFO) << "kHasToggledState:" + << node.HasFlag(FLAGS_::kHasToggledState); + FML_DLOG(INFO) << "kIsToggled:" + << node.HasFlag(FLAGS_::kIsToggled); + FML_DLOG(INFO) << "kHasImplicitScrolling:" + << node.HasFlag(FLAGS_::kHasImplicitScrolling); + FML_DLOG(INFO) << "kIsMultiline:" + << node.HasFlag(FLAGS_::kIsMultiline); + FML_DLOG(INFO) << "kIsReadOnly:" + << node.HasFlag(FLAGS_::kIsReadOnly); + FML_DLOG(INFO) << "kIsFocusable:" + << node.HasFlag(FLAGS_::kIsFocusable); + FML_DLOG(INFO) << "kIsLink:" + << node.HasFlag(FLAGS_::kIsLink); + FML_DLOG(INFO) << "kIsSlider:" + << node.HasFlag(FLAGS_::kIsSlider); + FML_DLOG(INFO) << "kIsKeyboardKey:" + << node.HasFlag(FLAGS_::kIsKeyboardKey); + FML_DLOG(INFO) << "kIsCheckStateMixed:" + << node.HasFlag(FLAGS_::kIsCheckStateMixed); + FML_DLOG(INFO) << "----------------SemanticsFlags--------------------"; } -void OhosAccessibilityBridge::printTestActions( +void OhosAccessibilityBridge::GetCustomActionDebugInfo( flutter::CustomAccessibilityAction customAccessibilityAction) { - FML_DLOG(INFO) << "----------------SemanticsAction-------------------------"; + FML_DLOG(INFO) << "--------------CustomAccessibilityAction------------"; FML_DLOG(INFO) << "customAccessibilityAction.id=" << customAccessibilityAction.id; FML_DLOG(INFO) << "customAccessibilityAction.overrideId=" @@ -1522,7 +1680,7 @@ void OhosAccessibilityBridge::printTestActions( << customAccessibilityAction.label; FML_DLOG(INFO) << "customAccessibilityAction.hint=" << customAccessibilityAction.hint; - FML_DLOG(INFO) << "----------------SemanticsAction--------------------"; + FML_DLOG(INFO) << "------------CustomAccessibilityAction--------------"; } } // namespace flutter diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 138af72290..a8678794b6 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -99,7 +99,13 @@ class OhosAccessibilityBridge { std::string GetNodeComponentType(const flutter::SemanticsNode& node); flutter::SemanticsAction ArkuiActionsToFlutterActions(ArkUI_Accessibility_ActionType arkui_action); + bool IsNodeCheckable(flutter::SemanticsNode flutterNode); + bool IsNodeChecked(flutter::SemanticsNode flutterNode); + bool IsNodeSelected(flutter::SemanticsNode flutterNode); + bool IsNodeClickable(flutter::SemanticsNode flutterNode); bool IsNodeScrollable(flutter::SemanticsNode flutterNode); + bool IsNodePassword(flutter::SemanticsNode flutterNode); + bool IsNodeVisible(flutter::SemanticsNode flutterNode); void PerformSetText(flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments); void PerformSelectText(flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments); @@ -108,8 +114,9 @@ class OhosAccessibilityBridge { void onWindowNameChange(flutter::SemanticsNode route); void removeSemanticsNode(flutter::SemanticsNode nodeToBeRemoved); - void printTest(flutter::SemanticsNode node); - void printTestActions(flutter::CustomAccessibilityAction customAccessibilityAction); + void GetSemanticsNodeDebugInfo(flutter::SemanticsNode node); + void GetSemanticsFlagsDebugInfo(flutter::SemanticsNode node); + void GetCustomActionDebugInfo(flutter::CustomAccessibilityAction customAccessibilityAction); }; } // namespace flutter -- Gitee From 6f82a46de5a66b70953916a36cd88d2b199b5544 Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 25 Sep 2024 21:38:03 +0800 Subject: [PATCH 044/151] =?UTF-8?q?fix:=E5=AE=8C=E5=96=84=E5=8F=AF?= =?UTF-8?q?=E7=82=B9=E5=87=BB=E8=8A=82=E7=82=B9=E7=BB=84=E4=BB=B6=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos/accessibility/ohos_accessibility_bridge.cpp | 1 - .../ohos/accessibility/ohos_accessibility_manager.h | 8 -------- 2 files changed, 9 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 7f8b6efec4..daec84cd9a 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -789,7 +789,6 @@ bool OhosAccessibilityBridge::IsNodeClickable(flutter::SemanticsNode flutterNode || flutterNode.HasFlag(FLAGS_::kIsButton) || flutterNode.HasFlag(FLAGS_::kIsTextField) || flutterNode.HasFlag(FLAGS_::kIsImage) - || flutterNode.HasFlag(FLAGS_::kIsHeader) || flutterNode.HasFlag(FLAGS_::kIsLiveRegion) || flutterNode.HasFlag(FLAGS_::kIsMultiline) || flutterNode.HasFlag(FLAGS_::kIsLink) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_manager.h b/shell/platform/ohos/accessibility/ohos_accessibility_manager.h index e56df52733..d32e76173e 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_manager.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_manager.h @@ -15,14 +15,6 @@ #ifndef OHOS_ACCESSIBILITY_MANAGER_H #define OHOS_ACCESSIBILITY_MANAGER_H -// #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" -// #include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" -// #include "types.h" -// #include "ohos_logging.h" -// #include "flutter/fml/logging.h" -// #include - -// #include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" namespace flutter { /** -- Gitee From b033cf8878e93b635ee14736c09882ddd775b891 Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 26 Sep 2024 09:39:10 +0800 Subject: [PATCH 045/151] =?UTF-8?q?refactor:=E6=A0=BC=E5=BC=8F=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 170 +++++++++--------- .../accessibility/ohos_accessibility_bridge.h | 29 ++- 2 files changed, 103 insertions(+), 96 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index daec84cd9a..0288db8497 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -47,7 +47,7 @@ void OhosAccessibilityBridge::updateSemantics( const flutter::SemanticsNode& node = item.second; // print semantics node and flags info for debugging - GetSemanticsNodeDebugInfo(node); + GetSemanticsNodeDebugInfo(node); GetSemanticsFlagsDebugInfo(node); /** @@ -694,7 +694,8 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetAccessibilityText = " << text; std::string hint = flutterNode.hint; - OH_ArkUI_AccessibilityElementInfoSetHintText(elementInfoFromList, hint.c_str()); + OH_ArkUI_AccessibilityElementInfoSetHintText(elementInfoFromList, + hint.c_str()); // 配置child节点信息 int32_t childCount = @@ -713,49 +714,56 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( /** * 根据当前flutter节点的SemanticsFlags特性,配置对应的elementinfo属性 */ - //判断当前节点是否可点击 - if(IsNodeClickable(flutterNode)) { + // 判断当前节点是否可点击 + if (IsNodeClickable(flutterNode)) { OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); - FML_DLOG(INFO) <<"flutterNode.id="< true"; - } - //判断当前节点是否可获焦点 + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetClickable -> true"; + } + // 判断当前节点是否可获焦点 if (IsNodeFocusable(flutterNode)) { OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true); - FML_DLOG(INFO) <<"flutterNode.id="< true"; - } - //判断当前节点是否为密码输入框 - if(IsNodePassword(flutterNode)) { + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetFocusable -> true"; + } + // 判断当前节点是否为密码输入框 + if (IsNodePassword(flutterNode)) { OH_ArkUI_AccessibilityElementInfoSetIsPassword(elementInfoFromList, true); - FML_DLOG(INFO) <<"flutterNode.id="< true"; + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetIsPassword -> true"; } - //判断当前节点是否具备checkable状态 (如:checkbox, radio button) - if(IsNodeCheckable(flutterNode)) { + // 判断当前节点是否具备checkable状态 (如:checkbox, radio button) + if (IsNodeCheckable(flutterNode)) { OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true); - FML_DLOG(INFO) <<"flutterNode.id="< true"; + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetCheckable -> true"; } - //判断当前节点(check box/radio button)是否checked/unchecked - if(IsNodeChecked(flutterNode)) { + // 判断当前节点(check box/radio button)是否checked/unchecked + if (IsNodeChecked(flutterNode)) { OH_ArkUI_AccessibilityElementInfoSetChecked(elementInfoFromList, true); - FML_DLOG(INFO) <<"flutterNode.id="< true"; + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetChecked -> true"; } - //判断当前节点组件是否可显示 - if(IsNodeVisible(flutterNode)) { + // 判断当前节点组件是否可显示 + if (IsNodeVisible(flutterNode)) { OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true); - FML_DLOG(INFO) <<"flutterNode.id="< true"; + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetVisible -> true"; } - //判断当前节点组件是否选中 - if(IsNodeSelected(flutterNode)) { + // 判断当前节点组件是否选中 + if (IsNodeSelected(flutterNode)) { OH_ArkUI_AccessibilityElementInfoSetSelected(elementInfoFromList, true); - FML_DLOG(INFO) <<"flutterNode.id="< true"; + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetSelected -> true"; } - //当前节点组件默认enabled + // 当前节点组件默认enabled OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true); // 获取当前节点的组件类型 std::string componentTypeName = GetNodeComponentType(flutterNode); FML_DLOG(INFO) << "FlutterNodeToElementInfoById componentTypeName = " << componentTypeName; - //flutter节点对应elementinfo所属的组件类型(如:root, button,text等) + // flutter节点对应elementinfo所属的组件类型(如:root, button,text等) if (elementId == 0) { OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root"); @@ -784,51 +792,57 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( /** * 判断当前flutter节点组件是否可点击 */ -bool OhosAccessibilityBridge::IsNodeClickable(flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kHasCheckedState) - || flutterNode.HasFlag(FLAGS_::kIsButton) - || flutterNode.HasFlag(FLAGS_::kIsTextField) - || flutterNode.HasFlag(FLAGS_::kIsImage) - || flutterNode.HasFlag(FLAGS_::kIsLiveRegion) - || flutterNode.HasFlag(FLAGS_::kIsMultiline) - || flutterNode.HasFlag(FLAGS_::kIsLink) - || flutterNode.HasFlag(FLAGS_::kIsSlider) - || flutterNode.HasFlag(FLAGS_::kIsKeyboardKey) - || flutterNode.HasFlag(FLAGS_::kHasToggledState) - || flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); +bool OhosAccessibilityBridge::IsNodeClickable( + flutter::SemanticsNode flutterNode) { + return flutterNode.HasFlag(FLAGS_::kHasCheckedState) || + flutterNode.HasFlag(FLAGS_::kIsButton) || + flutterNode.HasFlag(FLAGS_::kIsTextField) || + flutterNode.HasFlag(FLAGS_::kIsImage) || + flutterNode.HasFlag(FLAGS_::kIsLiveRegion) || + flutterNode.HasFlag(FLAGS_::kIsMultiline) || + flutterNode.HasFlag(FLAGS_::kIsLink) || + flutterNode.HasFlag(FLAGS_::kIsSlider) || + flutterNode.HasFlag(FLAGS_::kIsKeyboardKey) || + flutterNode.HasFlag(FLAGS_::kHasToggledState) || + flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); } /** * 判断当前flutter节点组件是否可显示 */ -bool OhosAccessibilityBridge::IsNodeVisible(flutter::SemanticsNode flutterNode) { +bool OhosAccessibilityBridge::IsNodeVisible( + flutter::SemanticsNode flutterNode) { return flutterNode.HasFlag(FLAGS_::kIsHidden) ? false : true; } /** * 判断当前flutter节点组件是否具备checkable属性 */ -bool OhosAccessibilityBridge::IsNodeCheckable(flutter::SemanticsNode flutterNode) { +bool OhosAccessibilityBridge::IsNodeCheckable( + flutter::SemanticsNode flutterNode) { return flutterNode.HasFlag(FLAGS_::kHasCheckedState); } /** * 判断当前flutter节点组件是否checked/unchecked(checkbox、radio button) */ -bool OhosAccessibilityBridge::IsNodeChecked(flutter::SemanticsNode flutterNode) { +bool OhosAccessibilityBridge::IsNodeChecked( + flutter::SemanticsNode flutterNode) { return flutterNode.HasFlag(FLAGS_::kIsChecked); } /** * 判断当前flutter节点组件是否选中 */ -bool OhosAccessibilityBridge::IsNodeSelected(flutter::SemanticsNode flutterNode) { +bool OhosAccessibilityBridge::IsNodeSelected( + flutter::SemanticsNode flutterNode) { return flutterNode.HasFlag(FLAGS_::kIsSelected); } /** * 判断当前flutter节点组件是否为密码输入框 */ -bool OhosAccessibilityBridge::IsNodePassword(flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kIsTextField) && flutterNode.HasFlag(FLAGS_::kIsObscured); +bool OhosAccessibilityBridge::IsNodePassword( + flutter::SemanticsNode flutterNode) { + return flutterNode.HasFlag(FLAGS_::kIsTextField) && + flutterNode.HasFlag(FLAGS_::kIsObscured); } - /** * Called to obtain element information based on a specified node. * NOTE:该arkui接口需要在系统无障碍服务开启时,才能触发调用 @@ -1544,7 +1558,8 @@ void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() { flutterNavigationVec_.clear(); } -void OhosAccessibilityBridge::GetSemanticsNodeDebugInfo(flutter::SemanticsNode node) { +void OhosAccessibilityBridge::GetSemanticsNodeDebugInfo( + flutter::SemanticsNode node) { FML_DLOG(INFO) << "-------------------SemanticsNode------------------"; SkMatrix _transform = node.transform.asM33(); FML_DLOG(INFO) << "node.id=" << node.id; @@ -1611,58 +1626,39 @@ void OhosAccessibilityBridge::GetSemanticsNodeDebugInfo(flutter::SemanticsNode n FML_DLOG(INFO) << "------------------SemanticsNode-----------------"; } -void OhosAccessibilityBridge::GetSemanticsFlagsDebugInfo(flutter::SemanticsNode node) { +void OhosAccessibilityBridge::GetSemanticsFlagsDebugInfo( + flutter::SemanticsNode node) { FML_DLOG(INFO) << "----------------SemanticsFlags-------------------------"; FML_DLOG(INFO) << "kHasCheckedState: " << node.HasFlag(FLAGS_::kHasCheckedState); - FML_DLOG(INFO) << "kIsChecked:" - << node.HasFlag(FLAGS_::kIsChecked); - FML_DLOG(INFO) << "kIsSelected:" - << node.HasFlag(FLAGS_::kIsSelected); - FML_DLOG(INFO) << "kIsButton:" - << node.HasFlag(FLAGS_::kIsButton); - FML_DLOG(INFO) << "kIsTextField:" - << node.HasFlag(FLAGS_::kIsTextField); - FML_DLOG(INFO) << "kIsFocused:" - << node.HasFlag(FLAGS_::kIsFocused); + FML_DLOG(INFO) << "kIsChecked:" << node.HasFlag(FLAGS_::kIsChecked); + FML_DLOG(INFO) << "kIsSelected:" << node.HasFlag(FLAGS_::kIsSelected); + FML_DLOG(INFO) << "kIsButton:" << node.HasFlag(FLAGS_::kIsButton); + FML_DLOG(INFO) << "kIsTextField:" << node.HasFlag(FLAGS_::kIsTextField); + FML_DLOG(INFO) << "kIsFocused:" << node.HasFlag(FLAGS_::kIsFocused); FML_DLOG(INFO) << "kHasEnabledState:" << node.HasFlag(FLAGS_::kHasEnabledState); - FML_DLOG(INFO) << "kIsEnabled:" - << node.HasFlag(FLAGS_::kIsEnabled); + FML_DLOG(INFO) << "kIsEnabled:" << node.HasFlag(FLAGS_::kIsEnabled); FML_DLOG(INFO) << "kIsInMutuallyExclusiveGroup:" << node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup); - FML_DLOG(INFO) << "kIsHeader:" - << node.HasFlag(FLAGS_::kIsHeader); - FML_DLOG(INFO) << "kIsObscured:" - << node.HasFlag(FLAGS_::kIsObscured); - FML_DLOG(INFO) << "kScopesRoute:" - << node.HasFlag(FLAGS_::kScopesRoute); - FML_DLOG(INFO) << "kNamesRoute:" - << node.HasFlag(FLAGS_::kNamesRoute); - FML_DLOG(INFO) << "kIsHidden:" - << node.HasFlag(FLAGS_::kIsHidden); - FML_DLOG(INFO) << "kIsImage:" - << node.HasFlag(FLAGS_::kIsImage); - FML_DLOG(INFO) << "kIsLiveRegion:" - << node.HasFlag(FLAGS_::kIsLiveRegion); + FML_DLOG(INFO) << "kIsHeader:" << node.HasFlag(FLAGS_::kIsHeader); + FML_DLOG(INFO) << "kIsObscured:" << node.HasFlag(FLAGS_::kIsObscured); + FML_DLOG(INFO) << "kScopesRoute:" << node.HasFlag(FLAGS_::kScopesRoute); + FML_DLOG(INFO) << "kNamesRoute:" << node.HasFlag(FLAGS_::kNamesRoute); + FML_DLOG(INFO) << "kIsHidden:" << node.HasFlag(FLAGS_::kIsHidden); + FML_DLOG(INFO) << "kIsImage:" << node.HasFlag(FLAGS_::kIsImage); + FML_DLOG(INFO) << "kIsLiveRegion:" << node.HasFlag(FLAGS_::kIsLiveRegion); FML_DLOG(INFO) << "kHasToggledState:" << node.HasFlag(FLAGS_::kHasToggledState); - FML_DLOG(INFO) << "kIsToggled:" - << node.HasFlag(FLAGS_::kIsToggled); + FML_DLOG(INFO) << "kIsToggled:" << node.HasFlag(FLAGS_::kIsToggled); FML_DLOG(INFO) << "kHasImplicitScrolling:" << node.HasFlag(FLAGS_::kHasImplicitScrolling); - FML_DLOG(INFO) << "kIsMultiline:" - << node.HasFlag(FLAGS_::kIsMultiline); - FML_DLOG(INFO) << "kIsReadOnly:" - << node.HasFlag(FLAGS_::kIsReadOnly); - FML_DLOG(INFO) << "kIsFocusable:" - << node.HasFlag(FLAGS_::kIsFocusable); - FML_DLOG(INFO) << "kIsLink:" - << node.HasFlag(FLAGS_::kIsLink); - FML_DLOG(INFO) << "kIsSlider:" - << node.HasFlag(FLAGS_::kIsSlider); - FML_DLOG(INFO) << "kIsKeyboardKey:" - << node.HasFlag(FLAGS_::kIsKeyboardKey); + FML_DLOG(INFO) << "kIsMultiline:" << node.HasFlag(FLAGS_::kIsMultiline); + FML_DLOG(INFO) << "kIsReadOnly:" << node.HasFlag(FLAGS_::kIsReadOnly); + FML_DLOG(INFO) << "kIsFocusable:" << node.HasFlag(FLAGS_::kIsFocusable); + FML_DLOG(INFO) << "kIsLink:" << node.HasFlag(FLAGS_::kIsLink); + FML_DLOG(INFO) << "kIsSlider:" << node.HasFlag(FLAGS_::kIsSlider); + FML_DLOG(INFO) << "kIsKeyboardKey:" << node.HasFlag(FLAGS_::kIsKeyboardKey); FML_DLOG(INFO) << "kIsCheckStateMixed:" << node.HasFlag(FLAGS_::kIsCheckStateMixed); FML_DLOG(INFO) << "----------------SemanticsFlags--------------------"; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index a8678794b6..22901c8fbb 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -47,8 +47,8 @@ class OhosAccessibilityBridge { bool isOhosAccessibilityEnabled_; int64_t nativeShellHolder_; + ArkUI_AccessibilityProvider* provider_; - void updateSemantics(flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions); @@ -59,14 +59,20 @@ class OhosAccessibilityBridge { // obtain the flutter semnatics node flutter::SemanticsNode getOrCreateFlutterSemanticsNode(int32_t id); - int32_t FindAccessibilityNodeInfosById(int64_t elementId, ArkUI_AccessibilitySearchMode mode, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList); - int32_t FindAccessibilityNodeInfosByText(int64_t elementId, const char* text, int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList); - int32_t FindFocusedAccessibilityNode(int64_t elementId, ArkUI_AccessibilityFocusType focusType, int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo); - int32_t FindNextFocusAccessibilityNode(int64_t elementId, ArkUI_AccessibilityFocusMoveDirection direction, int32_t requestId, ArkUI_AccessibilityElementInfo* elementList); - int32_t ExecuteAccessibilityAction(int64_t elementId, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments *actionArguments, int32_t requestId); + int32_t FindAccessibilityNodeInfosById(int64_t elementId, ArkUI_AccessibilitySearchMode mode, + int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList); + int32_t FindAccessibilityNodeInfosByText(int64_t elementId, const char* text, int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList); + int32_t FindFocusedAccessibilityNode(int64_t elementId, ArkUI_AccessibilityFocusType focusType, + int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo); + int32_t FindNextFocusAccessibilityNode(int64_t elementId, ArkUI_AccessibilityFocusMoveDirection direction, + int32_t requestId, ArkUI_AccessibilityElementInfo* elementList); + int32_t ExecuteAccessibilityAction(int64_t elementId, ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments *actionArguments, + int32_t requestId); int32_t ClearFocusedFocusAccessibilityNode(); int32_t GetAccessibilityNodeCursorPosition(int64_t elementId, int32_t requestId, int32_t* index); - ArkUI_AccessibilityProvider* provider_; void Flutter_SendAccessibilityAsyncEvent(int64_t elementId, ArkUI_AccessibilityEventType eventType); void FlutterNodeToElementInfoById(ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId); @@ -106,8 +112,13 @@ class OhosAccessibilityBridge { bool IsNodeScrollable(flutter::SemanticsNode flutterNode); bool IsNodePassword(flutter::SemanticsNode flutterNode); bool IsNodeVisible(flutter::SemanticsNode flutterNode); - void PerformSetText(flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments); - void PerformSelectText(flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments); + + void PerformSetText(flutter::SemanticsNode flutterNode, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments); + void PerformSelectText(flutter::SemanticsNode flutterNode, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments); void AddRouteNodes(std::vector edges, flutter::SemanticsNode node); std::string GetRouteName(flutter::SemanticsNode node); -- Gitee From d8dba1a993c5ec9ab0254928ff172172d99fc1cb Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 26 Sep 2024 16:55:51 +0800 Subject: [PATCH 046/151] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E8=AF=AD?= =?UTF-8?q?=E4=B9=89=E6=A0=91=E8=8A=82=E7=82=B9=E7=BB=84=E4=BB=B6=E4=B8=8D?= =?UTF-8?q?=E8=83=BD=E9=9A=8F=E6=84=8F=E6=BB=91=E5=8A=A8=E7=84=A6=E7=82=B9?= =?UTF-8?q?=E6=A1=86=E7=9A=84bug=EF=BC=8C=E5=B9=B6=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E9=83=A8=E5=88=86=E5=8A=9F=E8=83=BD=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 124 +++++++++++------- .../accessibility/ohos_accessibility_bridge.h | 2 + 2 files changed, 82 insertions(+), 44 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 0288db8497..67442d3b68 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -215,6 +215,9 @@ void OhosAccessibilityBridge::updateSemantics( FML_DLOG(INFO) << "=== UpdateSemantics is end ==="; } +/** + * 判断是否可滑动 + */ bool OhosAccessibilityBridge::IsNodeScrollable( flutter::SemanticsNode flutterNode) { // int32_t scrollChildren = 0; @@ -224,6 +227,12 @@ bool OhosAccessibilityBridge::IsNodeScrollable( // double scrollExtentMin = std::nan(""); return flutterNode.scrollPosition != std::nan(""); } +/** + * 判断当前节点组件是否是滑动组件,如: listview, gridview等 + */ +bool OhosAccessibilityBridge::IsScrollableWidget(flutter::SemanticsNode flutterNode) { + return flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); +} void OhosAccessibilityBridge::announce(std::unique_ptr& message) { // 创建并设置屏幕朗读事件 @@ -395,16 +404,6 @@ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId << ", <" << left << ", " << top << ", " << right << ", " << bottom << "> } is succeed"; - // if (screenRectMap_.find(flutterNodeId) == screenRectMap_.end()) { - // screenRectMap_[flutterNodeId] = std::make_pair(std::make_pair(left, top), - // std::make_pair(right, bottom)); - // FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId - // << ", <" << left << ", " << top << ", " << right << ", " - // << bottom << "> } is succeed"; - // } else { - // FML_DLOG(ERROR) << "SetAbsoluteScreenRect -> flutterNodeId=" - // << flutterNodeId << " already exists !"; - // } } std::pair, std::pair> @@ -572,7 +571,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( childCount, childNodeIds); // 配置常用属性 - OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true); + OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true); @@ -604,69 +603,100 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( << flutterNode.id << " SceenRect = (" << left << ", " << top << ", " << right << ", " << bottom << ")"; - // 若为非文本类输入框组件 - if (!flutterNode.HasFlag(FLAGS_::kIsTextField)) { + //当节点为textfield文本输入框组件类型 + if (IsTextField(flutterNode)) { // 设置elementinfo的action类型 - int32_t actionTypeNum = 5; + int32_t actionTypeNum = 10; ArkUI_AccessibleAction actions[actionTypeNum]; + actions[0].actionType = ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; actions[0].description = "获取焦点"; + actions[1].actionType = ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; actions[1].description = "清除焦点"; + + actions[2].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; + actions[2].description = "点击操作"; + + actions[3].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK; + actions[3].description = "长按操作"; + + actions[4].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY; + actions[4].description = "文本复制"; + + actions[5].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE; + actions[5].description = "文本粘贴"; + + actions[6].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT; + actions[6].description = "文本剪切"; + + actions[7].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT; + actions[7].description = "文本选择"; + + actions[8].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT; + actions[8].description = "文本内容设置"; + + actions[9].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION; + actions[9].description = "光标位置设置"; + + OH_ArkUI_AccessibilityElementInfoSetOperationActions( + elementInfoFromList, actionTypeNum, actions); + + } else if(IsScrollableWidget(flutterNode)) { + // 当节点为可滑动组件 + int32_t actionTypeNum = 5; + ArkUI_AccessibleAction actions[actionTypeNum]; + + actions[0].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; + actions[0].description = "获取焦点"; + + actions[1].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].description = "清除焦点"; + actions[2].actionType = ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; actions[2].description = "点击动作"; + actions[3].actionType = ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD; actions[3].description = "向上滑动"; + actions[4].actionType = ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD; actions[4].description = "向下滑动"; + OH_ArkUI_AccessibilityElementInfoSetOperationActions( elementInfoFromList, actionTypeNum, actions); - } else { // 若为textfield文本输入框组件类型 + } else { // 设置elementinfo的action类型 - int32_t actionTypeNum = 12; + int32_t actionTypeNum = 3; ArkUI_AccessibleAction actions[actionTypeNum]; + actions[0].actionType = ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; actions[0].description = "获取焦点"; + actions[1].actionType = ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; actions[1].description = "清除焦点"; + actions[2].actionType = ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; - actions[2].description = "点击操作"; - actions[3].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD; - actions[3].description = "向上滑动"; - actions[4].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD; - actions[4].description = "向下滑动"; - actions[5].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK; - actions[5].description = "长按操作"; - actions[6].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY; - actions[6].description = "文本复制"; - actions[7].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE; - actions[7].description = "文本粘贴"; - actions[8].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT; - actions[8].description = "文本剪切"; - actions[9].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT; - actions[9].description = "文本选择"; - actions[10].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT; - actions[10].description = "文本内容设置"; - actions[11].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION; - actions[11].description = "光标位置设置"; + actions[2].description = "点击动作"; + OH_ArkUI_AccessibilityElementInfoSetOperationActions( elementInfoFromList, actionTypeNum, actions); } @@ -789,6 +819,12 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( << "=== OhosAccessibilityBridge::FlutterNodeToElementInfoById is end ==="; } +/** + * 判断当前节点是否为textfield文本框 + */ +bool OhosAccessibilityBridge::IsTextField(flutter::SemanticsNode flutterNode) { + return flutterNode.HasFlag(FLAGS_::kIsTextField); +} /** * 判断当前flutter节点组件是否可点击 */ diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 22901c8fbb..a810ba5183 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -113,6 +113,8 @@ class OhosAccessibilityBridge { bool IsNodePassword(flutter::SemanticsNode flutterNode); bool IsNodeVisible(flutter::SemanticsNode flutterNode); + bool IsTextField(flutter::SemanticsNode flutterNode); + bool IsScrollableWidget(flutter::SemanticsNode flutterNode); void PerformSetText(flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments); -- Gitee From b193d63152e646095970fc4196818ab01709d676 Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 26 Sep 2024 20:57:26 +0800 Subject: [PATCH 047/151] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 67442d3b68..b45e57793d 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -742,7 +742,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( childCount, childNodeIds); /** - * 根据当前flutter节点的SemanticsFlags特性,配置对应的elementinfo属性 + * 根据当前flutter节点的SemanticsFlags特性,配置对应的eelmentinfo属性 */ // 判断当前节点是否可点击 if (IsNodeClickable(flutterNode)) { -- Gitee From 453dd033a85075550d2bdaff3ddff6dfe2666642 Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 27 Sep 2024 09:32:16 +0800 Subject: [PATCH 048/151] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos/accessibility/ohos_accessibility_bridge.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index b45e57793d..51c9e06c0d 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -230,7 +230,8 @@ bool OhosAccessibilityBridge::IsNodeScrollable( /** * 判断当前节点组件是否是滑动组件,如: listview, gridview等 */ -bool OhosAccessibilityBridge::IsScrollableWidget(flutter::SemanticsNode flutterNode) { +bool OhosAccessibilityBridge::IsScrollableWidget( + flutter::SemanticsNode flutterNode) { return flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); } @@ -603,8 +604,8 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( << flutterNode.id << " SceenRect = (" << left << ", " << top << ", " << right << ", " << bottom << ")"; - //当节点为textfield文本输入框组件类型 - if (IsTextField(flutterNode)) { + // 当节点为textfield文本输入框组件类型 + if (IsTextField(flutterNode)) { // 设置elementinfo的action类型 int32_t actionTypeNum = 10; ArkUI_AccessibleAction actions[actionTypeNum]; @@ -652,7 +653,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( OH_ArkUI_AccessibilityElementInfoSetOperationActions( elementInfoFromList, actionTypeNum, actions); - } else if(IsScrollableWidget(flutterNode)) { + } else if (IsScrollableWidget(flutterNode)) { // 当节点为可滑动组件 int32_t actionTypeNum = 5; ArkUI_AccessibleAction actions[actionTypeNum]; @@ -662,7 +663,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( actions[0].description = "获取焦点"; actions[1].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; actions[1].description = "清除焦点"; actions[2].actionType = ArkUI_Accessibility_ActionType:: -- Gitee From 8d0f71a41d381998fd775b3d066ce34d4e8ba671 Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 27 Sep 2024 19:47:09 +0800 Subject: [PATCH 049/151] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E5=B1=8F?= =?UTF-8?q?=E5=B9=95=E6=9C=97=E8=AF=BB=E7=9A=84=E7=9B=B8=E5=AF=B9-?= =?UTF-8?q?=E7=BB=9D=E5=AF=B9=E5=9D=90=E6=A0=87=E8=BD=AC=E6=8D=A2=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E5=9C=A8=E6=BB=91=E5=8A=A8=E5=95=86=E5=93=81list?= =?UTF-8?q?=E6=97=B6=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 31 ++++-- .../accessibility/ohos_accessibility_bridge.h | 98 ++++++++++++------- 2 files changed, 87 insertions(+), 42 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 51c9e06c0d..bcc25f2ea9 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -487,20 +487,33 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( newBottom = (currTop + _kMTransY + currBottom) * realScaleFactor + realParentTop; } - SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); + + //若子节点rect超过父节点则跳过显示(单个屏幕显示不下,滑动再重新显示) + if (newLeft < realParentLeft || newTop < realParentTop || + newRight > realParentRight || newBottom > realParentBottom || + newLeft >= newRight || newTop >= newBottom) { + FML_DLOG(ERROR) << "ConvertChildRelativeRectToSceenRect childRect is " + "bigger than parentRect -> { nodeId: " + << currNode.id << ", (" << newLeft << ", " << newTop << ", " + << newRight << ", " << newBottom << ")}"; + SetAbsoluteScreenRect(currNode.id, newLeft, realParentTop-1260, realParentRight, realParentBottom-2720); + } else { + SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); + } + } FML_DLOG(INFO) << "ConvertChildRelativeRectToSceenRect -> { nodeId: " << currNode.id << ", (" << newLeft << ", " << newTop << ", " << newRight << ", " << newBottom << ")}"; - if (newLeft < realParentLeft || newTop < realParentTop || - newRight > realParentRight || newBottom > realParentBottom || - newLeft >= newRight || newTop >= newBottom) { - FML_DLOG(ERROR) << "ConvertChildRelativeRectToSceenRect childRect is " - "bigger than parentRect -> { nodeId: " - << currNode.id << ", (" << newLeft << ", " << newTop << ", " - << newRight << ", " << newBottom << ")}"; - } + // if (newLeft < realParentLeft || newTop < realParentTop || + // newRight > realParentRight || newBottom > realParentBottom || + // newLeft >= newRight || newTop >= newBottom) { + // FML_DLOG(ERROR) << "ConvertChildRelativeRectToSceenRect childRect is " + // "bigger than parentRect -> { nodeId: " + // << currNode.id << ", (" << newLeft << ", " << newTop << ", " + // << newRight << ", " << newBottom << ")}"; + // } } /** diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index a810ba5183..25881b2cc0 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -15,12 +15,12 @@ #ifndef OHOS_ACCESSIBILITY_BRIDGE_H #define OHOS_ACCESSIBILITY_BRIDGE_H +#include #include #include #include -#include #include -#include +#include #include "flutter/fml/log_level.h" #include "flutter/lib/ui/semantics/custom_accessibility_action.h" @@ -28,7 +28,6 @@ #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_manager.h" #include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" - namespace flutter { typedef flutter::SemanticsFlags FLAGS_; @@ -52,45 +51,74 @@ class OhosAccessibilityBridge { void updateSemantics(flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions); - void DispatchSemanticsAction(int32_t id, flutter::SemanticsAction action, fml::MallocMapping args); + void DispatchSemanticsAction(int32_t id, + flutter::SemanticsAction action, + fml::MallocMapping args); void announce(std::unique_ptr& message); // obtain the flutter semnatics node flutter::SemanticsNode getOrCreateFlutterSemanticsNode(int32_t id); - int32_t FindAccessibilityNodeInfosById(int64_t elementId, ArkUI_AccessibilitySearchMode mode, - int32_t requestId, - ArkUI_AccessibilityElementInfoList* elementList); - int32_t FindAccessibilityNodeInfosByText(int64_t elementId, const char* text, int32_t requestId, - ArkUI_AccessibilityElementInfoList* elementList); - int32_t FindFocusedAccessibilityNode(int64_t elementId, ArkUI_AccessibilityFocusType focusType, - int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo); - int32_t FindNextFocusAccessibilityNode(int64_t elementId, ArkUI_AccessibilityFocusMoveDirection direction, - int32_t requestId, ArkUI_AccessibilityElementInfo* elementList); - int32_t ExecuteAccessibilityAction(int64_t elementId, ArkUI_Accessibility_ActionType action, - ArkUI_AccessibilityActionArguments *actionArguments, - int32_t requestId); + int32_t FindAccessibilityNodeInfosById( + int64_t elementId, + ArkUI_AccessibilitySearchMode mode, + int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList); + int32_t FindAccessibilityNodeInfosByText( + int64_t elementId, + const char* text, + int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList); + int32_t FindFocusedAccessibilityNode( + int64_t elementId, + ArkUI_AccessibilityFocusType focusType, + int32_t requestId, + ArkUI_AccessibilityElementInfo* elementinfo); + int32_t FindNextFocusAccessibilityNode( + int64_t elementId, + ArkUI_AccessibilityFocusMoveDirection direction, + int32_t requestId, + ArkUI_AccessibilityElementInfo* elementList); + int32_t ExecuteAccessibilityAction( + int64_t elementId, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments, + int32_t requestId); int32_t ClearFocusedFocusAccessibilityNode(); - int32_t GetAccessibilityNodeCursorPosition(int64_t elementId, int32_t requestId, int32_t* index); - - void Flutter_SendAccessibilityAsyncEvent(int64_t elementId, ArkUI_AccessibilityEventType eventType); - void FlutterNodeToElementInfoById(ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId); + int32_t GetAccessibilityNodeCursorPosition(int64_t elementId, + int32_t requestId, + int32_t* index); + + void Flutter_SendAccessibilityAsyncEvent( + int64_t elementId, + ArkUI_AccessibilityEventType eventType); + void FlutterNodeToElementInfoById( + ArkUI_AccessibilityElementInfo* elementInfoFromList, + int64_t elementId); int32_t GetParentId(int64_t elementId); void ConvertChildRelativeRectToSceenRect(flutter::SemanticsNode node); - std::pair, std::pair> GetAbsoluteScreenRect(int32_t flutterNodeId); - void SetAbsoluteScreenRect(int32_t flutterNodeId, float left, float top, float right, float bottom); + std::pair, std::pair> + GetAbsoluteScreenRect(int32_t flutterNodeId); + void SetAbsoluteScreenRect(int32_t flutterNodeId, + float left, + float top, + float right, + float bottom); void ClearFlutterSemanticsCaches(); private: - static OhosAccessibilityBridge bridgeInstance; + static OhosAccessibilityBridge bridgeInstance; std::shared_ptr ax_manager_; std::vector> parentChildIdVec; std::unordered_map flutterSemanticsTree_; - std::unordered_map, std::pair>> screenRectMap_; + std::unordered_map< + int32_t, + std::pair, std::pair>> + screenRectMap_; std::unordered_map actions_mp_; std::vector flutterNavigationVec_; @@ -98,12 +126,14 @@ class OhosAccessibilityBridge { constexpr static const double SCROLL_EXTENT_FOR_INFINITY = 100000.0; constexpr static const double SCROLL_POSITION_CAP_FOR_INFINITY = 70000.0; - void FlutterTreeToArkuiTree(ArkUI_AccessibilityElementInfoList* elementInfoList); + void FlutterTreeToArkuiTree( + ArkUI_AccessibilityElementInfoList* elementInfoList); flutter::SemanticsNode getFlutterRootSemanticsNode(); bool IsNodeFocusable(const flutter::SemanticsNode& node); std::string GetNodeComponentType(const flutter::SemanticsNode& node); - flutter::SemanticsAction ArkuiActionsToFlutterActions(ArkUI_Accessibility_ActionType arkui_action); + flutter::SemanticsAction ArkuiActionsToFlutterActions( + ArkUI_Accessibility_ActionType arkui_action); bool IsNodeCheckable(flutter::SemanticsNode flutterNode); bool IsNodeChecked(flutter::SemanticsNode flutterNode); @@ -115,21 +145,23 @@ class OhosAccessibilityBridge { bool IsTextField(flutter::SemanticsNode flutterNode); bool IsScrollableWidget(flutter::SemanticsNode flutterNode); - void PerformSetText(flutter::SemanticsNode flutterNode, - ArkUI_Accessibility_ActionType action, + void PerformSetText(flutter::SemanticsNode flutterNode, + ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments); - void PerformSelectText(flutter::SemanticsNode flutterNode, - ArkUI_Accessibility_ActionType action, + void PerformSelectText(flutter::SemanticsNode flutterNode, + ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments); - void AddRouteNodes(std::vector edges, flutter::SemanticsNode node); + void AddRouteNodes(std::vector edges, + flutter::SemanticsNode node); std::string GetRouteName(flutter::SemanticsNode node); void onWindowNameChange(flutter::SemanticsNode route); void removeSemanticsNode(flutter::SemanticsNode nodeToBeRemoved); - + void GetSemanticsNodeDebugInfo(flutter::SemanticsNode node); void GetSemanticsFlagsDebugInfo(flutter::SemanticsNode node); - void GetCustomActionDebugInfo(flutter::CustomAccessibilityAction customAccessibilityAction); + void GetCustomActionDebugInfo( + flutter::CustomAccessibilityAction customAccessibilityAction); }; } // namespace flutter -- Gitee From 0ae40c7c6643f77a79af4f46f5560ec755f5d4a6 Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 27 Sep 2024 20:58:31 +0800 Subject: [PATCH 050/151] =?UTF-8?q?refactor:=E5=B0=86=E5=AE=B9=E5=99=A8?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E4=B8=BA=E7=BB=93=E6=9E=84=E4=BD=93=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E5=AD=98=E5=82=A8=EF=BC=8C=E5=87=8F=E5=B0=91=E5=BC=80?= =?UTF-8?q?=E9=94=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../accessibility/ohos_accessibility_bridge.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 25881b2cc0..0079a12760 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -37,6 +37,22 @@ typedef flutter::SemanticsNode FLUTTER_NODE_; /** * flutter和ohos的无障碍服务桥接 */ +struct AbsoluteRect { + float left; + float top; + float right; + float bottom; + + static constexpr AbsoluteRect MakeEmpty() { + return AbsoluteRect{0.0, 0.0, 0.0, 0.0}; + } +}; + +struct SemanticsNodeExtent : flutter::SemanticsNode { + int32_t parentId = -1; + AbsoluteRect abRect = AbsoluteRect::MakeEmpty(); +}; + class OhosAccessibilityBridge { public: OhosAccessibilityBridge(); -- Gitee From 2bb6bb495efb2c8ed103cd350e0aca6aa29fee13 Mon Sep 17 00:00:00 2001 From: zjxi Date: Sun, 29 Sep 2024 11:42:08 +0800 Subject: [PATCH 051/151] =?UTF-8?q?refactor:=E5=B0=81=E8=A3=85set=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E5=B1=9E=E6=80=A7=E5=87=BD=E6=95=B0=EF=BC=8C=E5=87=8F?= =?UTF-8?q?=E5=B0=91=E8=80=A6=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 45 ++++++++++++------- .../accessibility/ohos_accessibility_bridge.h | 4 +- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index bcc25f2ea9..c1394ad5f9 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -600,13 +600,29 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( /** NOTE: when elementId >= 1 */ FML_DLOG(INFO) << "FlutterNodeToElementInfoById elementId = " << elementId; + + //根据flutter节点信息配置elementinfo无障碍属性 + FlutterSetElementInfoProperties(elementInfoFromList, elementId); + + FML_DLOG(INFO) + << "=== OhosAccessibilityBridge::FlutterNodeToElementInfoById is end ==="; +} + +/** + * 根据flutter节点信息配置elementinfo无障碍属性 + */ +void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_AccessibilityElementInfo* elementInfoFromList, + int64_t elementId) { flutter::SemanticsNode flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); - // flutter父子节点相对坐标位置的矩阵变换,转化为绝对屏幕坐标 + //set elementinfo id + OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, + flutterNode.id); + //convert relative rect to absolute rect ConvertChildRelativeRectToSceenRect(flutterNode); auto rectPairs = GetAbsoluteScreenRect(flutterNode.id); - // 设置elementinfo的屏幕绝对坐标rect + //set screen rect in xcomponent int32_t left = rectPairs.first.first; int32_t top = rectPairs.first.second; int32_t right = rectPairs.second.first; @@ -617,9 +633,9 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( << flutterNode.id << " SceenRect = (" << left << ", " << top << ", " << right << ", " << bottom << ")"; - // 当节点为textfield文本输入框组件类型 + // if node is textfield if (IsTextField(flutterNode)) { - // 设置elementinfo的action类型 + // set elementinfo action types int32_t actionTypeNum = 10; ArkUI_AccessibleAction actions[actionTypeNum]; @@ -667,7 +683,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( elementInfoFromList, actionTypeNum, actions); } else if (IsScrollableWidget(flutterNode)) { - // 当节点为可滑动组件 + //if node is scrollable component int32_t actionTypeNum = 5; ArkUI_AccessibleAction actions[actionTypeNum]; @@ -695,7 +711,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( elementInfoFromList, actionTypeNum, actions); } else { - // 设置elementinfo的action类型 + // set common component action types int32_t actionTypeNum = 3; ArkUI_AccessibleAction actions[actionTypeNum]; @@ -715,11 +731,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( elementInfoFromList, actionTypeNum, actions); } - // 根据flutternode信息配置对应的elementinfo - OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, - flutterNode.id); - - // 设置父节点id + //set current elementinfo parent id int32_t parentId = GetParentId(elementId); if (parentId < 0) { FML_DLOG(ERROR) @@ -731,17 +743,18 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( FML_DLOG(INFO) << "FlutterNodeToElementInfoById GetParentId = " << parentId; } - // 设置无障碍播报文本 + //set accessibility text for announcing std::string text = flutterNode.label; OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfoFromList, text.c_str()); FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetAccessibilityText = " << text; + std::string hint = flutterNode.hint; OH_ArkUI_AccessibilityElementInfoSetHintText(elementInfoFromList, hint.c_str()); - // 配置child节点信息 + //set chidren elementinfo ids int32_t childCount = static_cast(flutterNode.childrenInTraversalOrder.size()); int64_t childNodeIds[childCount]; @@ -756,9 +769,9 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( childCount, childNodeIds); /** - * 根据当前flutter节点的SemanticsFlags特性,配置对应的eelmentinfo属性 + * 根据当前flutter节点的SemanticsFlags特性,配置对应的elmentinfo属性 */ - // 判断当前节点是否可点击 + //判断当前节点是否可点击 if (IsNodeClickable(flutterNode)) { OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id @@ -829,8 +842,6 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( // 无障碍组,设置为true时表示该组件及其所有子组件为一整个可以选中的组件,无障碍服务将不再关注其子组件内容。默认值:false OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, false); - FML_DLOG(INFO) - << "=== OhosAccessibilityBridge::FlutterNodeToElementInfoById is end ==="; } /** diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 0079a12760..732605ffe8 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -142,15 +142,17 @@ class OhosAccessibilityBridge { constexpr static const double SCROLL_EXTENT_FOR_INFINITY = 100000.0; constexpr static const double SCROLL_POSITION_CAP_FOR_INFINITY = 70000.0; + void FlutterSetElementInfoProperties(ArkUI_AccessibilityElementInfo* elementInfoFromList, + int64_t elementId); void FlutterTreeToArkuiTree( ArkUI_AccessibilityElementInfoList* elementInfoList); flutter::SemanticsNode getFlutterRootSemanticsNode(); - bool IsNodeFocusable(const flutter::SemanticsNode& node); std::string GetNodeComponentType(const flutter::SemanticsNode& node); flutter::SemanticsAction ArkuiActionsToFlutterActions( ArkUI_Accessibility_ActionType arkui_action); + bool IsNodeFocusable(const flutter::SemanticsNode& node); bool IsNodeCheckable(flutter::SemanticsNode flutterNode); bool IsNodeChecked(flutter::SemanticsNode flutterNode); bool IsNodeSelected(flutter::SemanticsNode flutterNode); -- Gitee From c756d8ab75ebf364c51e4559d4500d1bc1faa486 Mon Sep 17 00:00:00 2001 From: zjxi Date: Sun, 29 Sep 2024 21:49:09 +0800 Subject: [PATCH 052/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0flutter=E8=AF=AD?= =?UTF-8?q?=E4=B9=89=E6=A0=91=E6=9B=B4=E6=96=B0=E4=B8=AD=E5=AF=B9=E6=BB=91?= =?UTF-8?q?=E5=8A=A8=E7=BB=84=E4=BB=B6=E7=9A=84=E6=89=A7=E8=A1=8C=E6=93=8D?= =?UTF-8?q?=E4=BD=9C,=E5=AE=9E=E7=8E=B0=E9=97=B2=E9=B1=BC=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E7=AD=89=E5=A4=8D=E6=9D=82=E7=83=AD=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E7=9A=84=E8=87=AA=E5=8A=A8=E6=BB=91=E5=8A=A8?= =?UTF-8?q?=E8=AF=86=E5=88=AB=E5=B9=B6=E6=9C=97=E8=AF=BB=E5=95=86=E5=93=81?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 335 ++++++++++-------- .../accessibility/ohos_accessibility_bridge.h | 30 +- 2 files changed, 212 insertions(+), 153 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index c1394ad5f9..5ae67c58b0 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -46,6 +46,9 @@ void OhosAccessibilityBridge::updateSemantics( // 获取当前更新的节点node const flutter::SemanticsNode& node = item.second; + // set struct SemanticsNodeExtent + auto nodeEx = SetAndGetSemanticsNodeExtent(node); + // print semantics node and flags info for debugging GetSemanticsNodeDebugInfo(node); GetSemanticsFlagsDebugInfo(node); @@ -76,123 +79,15 @@ void OhosAccessibilityBridge::updateSemantics( << ", " << node.childrenInTraversalOrder[i] << ")"; } - // 判断是否触发滑动操作 - if (IsNodeScrollable(node)) { - double nodePosition = node.scrollPosition; - double nodeScrollExtentMax = node.scrollExtentMax; - double nodeScrollExtentMin = node.scrollExtentMin; - double infinity = std::numeric_limits::infinity(); - // 设置flutter可滑动的最大范围值 - if (nodeScrollExtentMax == infinity) { - nodeScrollExtentMax = SCROLL_EXTENT_FOR_INFINITY; - if (nodePosition > SCROLL_POSITION_CAP_FOR_INFINITY) { - nodePosition = SCROLL_POSITION_CAP_FOR_INFINITY; - } - } - if (nodeScrollExtentMin == infinity) { - nodeScrollExtentMax += SCROLL_EXTENT_FOR_INFINITY; - if (nodePosition < -SCROLL_POSITION_CAP_FOR_INFINITY) { - nodePosition = -SCROLL_POSITION_CAP_FOR_INFINITY; - } - nodePosition += SCROLL_EXTENT_FOR_INFINITY; - } else { - nodeScrollExtentMax -= node.scrollExtentMin; - nodePosition -= node.scrollExtentMin; - } - - if (node.HasAction(ACTIONS_::kScrollUp) || - node.HasAction(ACTIONS_::kScrollDown)) { - // TODO: ohos/arkui未提供相应的滑动属性配置event - // event.setScrollY((int) nodePosition); - // event.setMaxScrollY((int) nodeScrollExtentMax); - } else if (node.HasAction(ACTIONS_::kScrollLeft) || - node.HasAction(ACTIONS_::kScrollRight)) { - // TODO: ohos/arkui未提供相应的滑动属性配置event - // event.setScrollX((int) nodePosition); - // event.setMaxScrollX((int) nodeScrollExtentMax); - } - if (node.scrollChildren > 0) { - // We don't need to add 1 to the scroll index because TalkBack does this - // automagically. event.setItemCount(object.scrollChildren); - // event.setFromIndex(object.scrollIndex); - int visibleChildren = 0; - // handle hidden children at the beginning and end of the list. - for (const auto& childId : node.childrenInHitTestOrder) { - auto childNode = getOrCreateFlutterSemanticsNode(childId); - if (!childNode.HasFlag(FLAGS_::kIsHidden)) { - visibleChildren += 1; - } - } - // TODO: 缺少ohos/arkui的滑动事件配置事件接口 - // event.setToIndex(object.scrollIndex + visibleChildren - 1); - } - // sendAccessibilityEvent(event) + //当滑动节点产生滑动,并执行滑动处理 + if(HasScrolled(node)) { + ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); + FlutterNodeToElementInfoById(_elementInfo, static_cast(node.id)); + FlutterScrollExecution(node, _elementInfo); } - // TODO: 若该对象是输入焦点节点,且发生更新变化,则发送给os有关它的信息 - // std::shared_ptr - // inputFocusedSemanticsNode; // 当前输入焦点节点 - // std::shared_ptr - // lastInputFocusedSemanticsNode; // 上一个输入焦点节点 - // bool isHadFlag = true; - // if (inputFocusedSemanticsNode != nullptr && - // inputFocusedSemanticsNode->id == node.id && - // (lastInputFocusedSemanticsNode == nullptr || - // lastInputFocusedSemanticsNode->id != - // inputFocusedSemanticsNode->id)) { - // // 上次输入焦点节点 -> 当前输入焦点节点 - // lastInputFocusedSemanticsNode = inputFocusedSemanticsNode; - // // 发送相应的输入焦点改变事件 - // // sendAccessibilityEvent(obtainAccessibilityEvent(object.id, - // // AccessibilityEvent.TYPE_VIEW_FOCUSED)); - // } else if (inputFocusedSemanticsNode == nullptr) { - // // There's no TYPE_VIEW_CLEAR_FOCUSED event, so if the current input - // focus - // // becomes null, then we just set the last one to null too, so that it - // // sends the event again when something regains focus. - // lastInputFocusedSemanticsNode = nullptr; - // } - - // if (inputFocusedSemanticsNode != nullptr && - // inputFocusedSemanticsNode->id == node.id && isHadFlag && - // node.HasFlag(FLAGS_::kIsTextField) - // // If we have a TextField that has InputFocus, we should avoid - // // announcing it if something else we track has a11y focus. This - // needs - // // to still work when, e.g., IME has a11y focus or the "PASTE" popup - // is - // // used though. See more discussion at - // // https://github.com/flutter/flutter/issues/23180 - // && (accessibilityFocusedSemanticsNode == nullptr || - // (accessibilityFocusedSemanticsNode->id == - // inputFocusedSemanticsNode->id))) { - // // - // 这里写输入框更新文字内容,将老旧的文本替换为新输入文字,并发送textchange事件 - // // AccessibilityEvent event = createTextChangedEvent(object.id, - // oldValue, - // // newValue); sendAccessibilityEvent(event); - - // // todo:若当前textselection部分和之前的textselection部分不同,则触发 - // int32_t previousTextSelectionBase = 0; - // int32_t previousTextSelectionExtent = 1; - // if (previousTextSelectionBase != node.textSelectionBase || - // previousTextSelectionExtent != node.textSelectionExtent) { - // // 创建并发送textselection改变事件 - // // AccessibilityEvent selectionEvent = obtainAccessibilityEvent( - // // object.id, - // AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); - // // selectionEvent.getText().add(newValue); - // // selectionEvent.setFromIndex(object.textSelectionBase); - // // selectionEvent.setToIndex(object.textSelectionExtent); - // // selectionEvent.setItemCount(newValue.length()); - // // sendAccessibilityEvent(selectionEvent); - // } - // } - - // 判断是否触发liveRegion活动区,当前节点是否活跃(优先级低) - if (node.HasFlag(FLAGS_::kIsLiveRegion)) { - // TODO: ... - } + //判断是否触发liveRegion活动区,当前节点是否活跃(暂不影响正常功能) + if (node.HasFlag(FLAGS_::kIsLiveRegion)) {} } // TODO: 遍历更新的actions,并将所有的actions的id添加进actionMap @@ -215,17 +110,139 @@ void OhosAccessibilityBridge::updateSemantics( FML_DLOG(INFO) << "=== UpdateSemantics is end ==="; } +void OhosAccessibilityBridge::FlutterScrollExecution(flutter::SemanticsNode node, + ArkUI_AccessibilityElementInfo* elementInfoFromList) { + + double nodePosition = node.scrollPosition; + double nodeScrollExtentMax = node.scrollExtentMax; + double nodeScrollExtentMin = node.scrollExtentMin; + double infinity = std::numeric_limits::infinity(); + // 设置flutter可滑动的最大范围值 + if (nodeScrollExtentMax == infinity) { + nodeScrollExtentMax = SCROLL_EXTENT_FOR_INFINITY; + if (nodePosition > SCROLL_POSITION_CAP_FOR_INFINITY) { + nodePosition = SCROLL_POSITION_CAP_FOR_INFINITY; + } + } + if (nodeScrollExtentMin == infinity) { + nodeScrollExtentMax += SCROLL_EXTENT_FOR_INFINITY; + if (nodePosition < -SCROLL_POSITION_CAP_FOR_INFINITY) { + nodePosition = -SCROLL_POSITION_CAP_FOR_INFINITY; + } + nodePosition += SCROLL_EXTENT_FOR_INFINITY; + } else { + nodeScrollExtentMax -= node.scrollExtentMin; + nodePosition -= node.scrollExtentMin; + } + + if (node.HasAction(ACTIONS_::kScrollUp) || + node.HasAction(ACTIONS_::kScrollDown)) { + // TODO: ohos/arkui未提供相应的滑动属性配置event (暂未影响正常功能) + } else if (node.HasAction(ACTIONS_::kScrollLeft) || + node.HasAction(ACTIONS_::kScrollRight)) { + // TODO: ohos/arkui未提供相应的滑动属性配置event (暂未影响正常功能) + } + + //当可滑动组件存在滑动子节点 + if (node.scrollChildren > 0) { + //配置当前滑动组件的子节点总数 + int32_t itemCount = node.scrollChildren; + OH_ArkUI_AccessibilityElementInfoSetItemCount(elementInfoFromList, itemCount); + + //设置当前滑动index + int32_t currentItemIndex = node.scrollIndex; + OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex(elementInfoFromList, currentItemIndex); + + //设置当前页面可见的起始滑动index + int32_t startItemIndex = node.scrollIndex; + OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, startItemIndex); + + //计算当前滑动位置页面的可见子滑动节点数量 + int visibleChildren = 0; + // handle hidden children at the beginning and end of the list. + for (const auto& childId : node.childrenInHitTestOrder) { + auto childNode = getOrCreateFlutterSemanticsNode(childId); + if (!childNode.HasFlag(FLAGS_::kIsHidden)) { + visibleChildren += 1; + } + } + //当可见滑动子节点数量超过滑动组件总子节点数量 + if (node.scrollIndex + visibleChildren > node.scrollChildren) { + FML_DLOG(ERROR) << "FlutterScrollExecution -> Scroll index is out of bounds"; + } + //当滑动击中子节点数量为0 + if (!node.childrenInHitTestOrder.size()) { + FML_DLOG(ERROR) << "FlutterScrollExecution -> Had scrollChildren but no childrenInHitTestOrder"; + } + + //设置当前页面可见的末尾滑动index + int32_t endItemIndex = node.scrollIndex + visibleChildren - 1; + OH_ArkUI_AccessibilityElementInfoSetEndItemIndex(elementInfoFromList, endItemIndex); + + } + //发送相应的事件到arkui无障碍子系统 + Flutter_SendAccessibilityAsyncEvent(static_cast(node.id), + ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED); +} + +/** + * extent common struct SemanticsNode to + * derived struct SemanticsNodeExtent + */ +SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent(flutter::SemanticsNode node) { + SemanticsNodeExtent nodeEx = SemanticsNodeExtent(); + nodeEx.id = std::move(node.id); + nodeEx.flags = std::move(node.flags); + nodeEx.actions = std::move(node.actions); + nodeEx.maxValueLength = std::move(node.maxValueLength); + nodeEx.currentValueLength = std::move(node.currentValueLength); + nodeEx.textSelectionBase = std::move(node.textSelectionBase); + nodeEx.textSelectionExtent = std::move(node.textSelectionExtent); + nodeEx.platformViewId = std::move(node.platformViewId); + nodeEx.scrollChildren = std::move(node.scrollChildren); + nodeEx.scrollIndex = std::move(node.scrollIndex); + nodeEx.scrollPosition = std::move(node.scrollPosition); + nodeEx.scrollExtentMax = std::move(node.scrollExtentMax); + nodeEx.scrollExtentMin = std::move(node.scrollExtentMin); + nodeEx.elevation = std::move(node.elevation); + nodeEx.thickness = std::move(node.thickness); + nodeEx.label = std::move(node.label); + nodeEx.labelAttributes = std::move(node.labelAttributes); + nodeEx.hint = std::move(node.hint); + nodeEx.hintAttributes = std::move(node.hintAttributes); + nodeEx.value = std::move(node.value); + nodeEx.valueAttributes = std::move(node.valueAttributes); + nodeEx.increasedValue = std::move(node.increasedValue); + nodeEx.increasedValueAttributes = std::move(node.increasedValueAttributes); + nodeEx.decreasedValue = std::move(node.decreasedValue); + nodeEx.decreasedValueAttributes = std::move(node.decreasedValueAttributes); + nodeEx.tooltip = std::move(node.tooltip); + nodeEx.textDirection = std::move(node.textDirection); + + nodeEx.rect = std::move(node.rect); + nodeEx.transform = std::move(node.transform); + nodeEx.childrenInTraversalOrder = std::move(node.childrenInTraversalOrder); + nodeEx.childrenInHitTestOrder = std::move(node.childrenInHitTestOrder); + nodeEx.customAccessibilityActions = std::move(node.customAccessibilityActions); + + return nodeEx; +} + +/** + * 判断当前节点是否已经滑动 + */ +bool OhosAccessibilityBridge::HasScrolled(const flutter::SemanticsNode& flutterNode) { + return flutterNode.scrollPosition != std::nan(""); +} /** * 判断是否可滑动 */ bool OhosAccessibilityBridge::IsNodeScrollable( flutter::SemanticsNode flutterNode) { - // int32_t scrollChildren = 0; - // int32_t scrollIndex = 0; - // double scrollPosition = std::nan(""); - // double scrollExtentMax = std::nan(""); - // double scrollExtentMin = std::nan(""); - return flutterNode.scrollPosition != std::nan(""); + return flutterNode.HasAction(ACTIONS_::kScrollLeft) + || flutterNode.HasAction(ACTIONS_::kScrollRight) + || flutterNode.HasAction(ACTIONS_::kScrollUp) + || flutterNode.HasAction(ACTIONS_::kScrollDown); } /** * 判断当前节点组件是否是滑动组件,如: listview, gridview等 @@ -235,6 +252,9 @@ bool OhosAccessibilityBridge::IsScrollableWidget( return flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); } +/** + * 主动播报特定文本 + */ void OhosAccessibilityBridge::announce(std::unique_ptr& message) { // 创建并设置屏幕朗读事件 ArkUI_AccessibilityEventInfo* announceEventInfo = @@ -454,6 +474,11 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( auto realParentRight = _rectPairs.second.first; auto realParentBottom = _rectPairs.second.second; + //获取root节点的绝对坐标 + auto _rootRect = GetAbsoluteScreenRect(0); + auto rootRight = _rootRect.second.first; + auto rootBottom = _rootRect.second.second; + // 真实缩放系数 float realScaleFactor = realParentRight / parentRight * 1.0; float newLeft, newTop, newRight, newBottom; @@ -475,11 +500,14 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( newRight = realParentRight; newBottom = realParentBottom; } else { - // 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 - // newLeft = (currLeft + _kMTransX) * realScaleFactor; - // newTop = (currTop + _kMTransY) * realScaleFactor; - // newRight = (currLeft + _kMTransX + currRight) * realScaleFactor; - // newBottom = (currTop + _kMTransY + currBottom) * realScaleFactor; + /** + * 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 (初期版本) + * newLeft = (currLeft + _kMTransX) * realScaleFactor; + * newTop = (currTop + _kMTransY) * realScaleFactor; + * newRight = (currLeft + _kMTransX + currRight) * realScaleFactor; + * newBottom = (currTop + _kMTransY + currBottom) * realScaleFactor; + */ + // 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 (增强版本) newLeft = (currLeft + _kMTransX) * realScaleFactor + realParentLeft; newTop = (currTop + _kMTransY) * realScaleFactor + realParentTop; newRight = @@ -496,7 +524,8 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( "bigger than parentRect -> { nodeId: " << currNode.id << ", (" << newLeft << ", " << newTop << ", " << newRight << ", " << newBottom << ")}"; - SetAbsoluteScreenRect(currNode.id, newLeft, realParentTop-1260, realParentRight, realParentBottom-2720); + SetAbsoluteScreenRect(currNode.id, newLeft, realParentTop-rootRight, realParentRight, realParentBottom-rootBottom); + } else { SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); } @@ -505,15 +534,6 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( FML_DLOG(INFO) << "ConvertChildRelativeRectToSceenRect -> { nodeId: " << currNode.id << ", (" << newLeft << ", " << newTop << ", " << newRight << ", " << newBottom << ")}"; - - // if (newLeft < realParentLeft || newTop < realParentTop || - // newRight > realParentRight || newBottom > realParentBottom || - // newLeft >= newRight || newTop >= newBottom) { - // FML_DLOG(ERROR) << "ConvertChildRelativeRectToSceenRect childRect is " - // "bigger than parentRect -> { nodeId: " - // << currNode.id << ", (" << newLeft << ", " << newTop << ", " - // << newRight << ", " << newBottom << ")}"; - // } } /** @@ -558,13 +578,13 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( // 根据flutternode信息配置对应的elementinfo OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, 0); - // NOTE: 系统强制设置root的父节点id = -2100000 + // NOTE: arkui无障碍子系统强制设置root的父节点id = -2100000 (严禁更改) OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, -2100000); // 设置无障碍播报文本 OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( elementInfoFromList, flutterNode.label.empty() - ? "root" - : flutterNode.label.c_str()); // debug + ? flutterNode.hint.c_str() + : flutterNode.label.c_str()); OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes"); OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, @@ -585,7 +605,6 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( childCount, childNodeIds); // 配置常用属性 - OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true); @@ -633,7 +652,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_Accessibilit << flutterNode.id << " SceenRect = (" << left << ", " << top << ", " << right << ", " << bottom << ")"; - // if node is textfield + // if node is a textfield if (IsTextField(flutterNode)) { // set elementinfo action types int32_t actionTypeNum = 10; @@ -682,8 +701,9 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_Accessibilit OH_ArkUI_AccessibilityElementInfoSetOperationActions( elementInfoFromList, actionTypeNum, actions); - } else if (IsScrollableWidget(flutterNode)) { - //if node is scrollable component + } else if (IsScrollableWidget(flutterNode) + || IsNodeScrollable(flutterNode)) { + //if node is a scrollable component int32_t actionTypeNum = 5; ArkUI_AccessibleAction actions[actionTypeNum]; @@ -749,7 +769,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_Accessibilit text.c_str()); FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetAccessibilityText = " << text; - + std::string hint = flutterNode.hint; OH_ArkUI_AccessibilityElementInfoSetHintText(elementInfoFromList, hint.c_str()); @@ -813,6 +833,23 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_Accessibilit FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetSelected -> true"; } + //判断当前节点组件是否可滑动 + if(IsNodeScrollable(flutterNode)) { + OH_ArkUI_AccessibilityElementInfoSetScrollable(elementInfoFromList, true); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetScrollable -> true"; + } + //判断当前节点组件是否可编辑(文本输入框) + if(IsTextField(flutterNode)) { + OH_ArkUI_AccessibilityElementInfoSetEditable(elementInfoFromList, true); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetEditable -> true"; + } + if(IsSlider(flutterNode)) { + //TODO 动态改变滑动条的值 + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetRangeInfo -> true"; + } // 当前节点组件默认enabled OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true); @@ -850,6 +887,12 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_Accessibilit bool OhosAccessibilityBridge::IsTextField(flutter::SemanticsNode flutterNode) { return flutterNode.HasFlag(FLAGS_::kIsTextField); } +/** + * 判断当前节点是否为滑动条slider类型 + */ +bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) { + return flutterNode.HasFlag(FLAGS_::kIsSlider); +} /** * 判断当前flutter节点组件是否可点击 */ @@ -937,9 +980,6 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } - // 将flutter语义节点树 -> arkui语义节点树 - // FlutterTreeToArkuiTree(elementList); - if (mode == ArkUI_AccessibilitySearchMode:: ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { /** Search for current nodes. (mode = 0) */ @@ -1586,7 +1626,6 @@ void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { void OhosAccessibilityBridge::removeSemanticsNode( flutter::SemanticsNode nodeToBeRemoved) { - // todo ... if (!flutterSemanticsTree_.size()) { FML_DLOG(ERROR) << "OhosAccessibilityBridge::removeSemanticsNode -> " "flutterSemanticsTree_.szie()=0"; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 732605ffe8..c5dd598577 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -51,6 +51,16 @@ struct AbsoluteRect { struct SemanticsNodeExtent : flutter::SemanticsNode { int32_t parentId = -1; AbsoluteRect abRect = AbsoluteRect::MakeEmpty(); + + int32_t previousFlags; + int32_t previousActions; + int32_t previousTextSelectionBase; + int32_t previousTextSelectionExtent; + float previousScrollPosition; + float previousScrollExtentMax; + float previousScrollExtentMin; + std::string previousValue; + std::string previousLabel; }; class OhosAccessibilityBridge { @@ -123,10 +133,21 @@ class OhosAccessibilityBridge { float right, float bottom); + SemanticsNodeExtent SetAndGetSemanticsNodeExtent(flutter::SemanticsNode node); + + void FlutterScrollExecution(flutter::SemanticsNode node, + ArkUI_AccessibilityElementInfo* elementInfoFromList); + void ClearFlutterSemanticsCaches(); private: static OhosAccessibilityBridge bridgeInstance; + static const int32_t ROOT_NODE_ID = 0; + constexpr static const double SCROLL_EXTENT_FOR_INFINITY = 100000.0; + constexpr static const double SCROLL_POSITION_CAP_FOR_INFINITY = 70000.0; + flutter::SemanticsNode inputFocusedNode; + flutter::SemanticsNode lastInputFocusedNode; + flutter::SemanticsNode accessibilityFocusedNode; std::shared_ptr ax_manager_; std::vector> parentChildIdVec; @@ -138,10 +159,6 @@ class OhosAccessibilityBridge { std::unordered_map actions_mp_; std::vector flutterNavigationVec_; - static const int32_t ROOT_NODE_ID = 0; - constexpr static const double SCROLL_EXTENT_FOR_INFINITY = 100000.0; - constexpr static const double SCROLL_POSITION_CAP_FOR_INFINITY = 70000.0; - void FlutterSetElementInfoProperties(ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId); void FlutterTreeToArkuiTree( @@ -152,7 +169,9 @@ class OhosAccessibilityBridge { flutter::SemanticsAction ArkuiActionsToFlutterActions( ArkUI_Accessibility_ActionType arkui_action); - bool IsNodeFocusable(const flutter::SemanticsNode& node); + bool HasScrolled(const flutter::SemanticsNode& flutterNode); + + bool IsNodeFocusable(const flutter::SemanticsNode& flutterNode); bool IsNodeCheckable(flutter::SemanticsNode flutterNode); bool IsNodeChecked(flutter::SemanticsNode flutterNode); bool IsNodeSelected(flutter::SemanticsNode flutterNode); @@ -162,6 +181,7 @@ class OhosAccessibilityBridge { bool IsNodeVisible(flutter::SemanticsNode flutterNode); bool IsTextField(flutter::SemanticsNode flutterNode); + bool IsSlider(flutter::SemanticsNode flutterNode); bool IsScrollableWidget(flutter::SemanticsNode flutterNode); void PerformSetText(flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, -- Gitee From 01a63144dfdcb2747f1693b87e307bdb3824cb8e Mon Sep 17 00:00:00 2001 From: zjxi Date: Sun, 29 Sep 2024 22:10:41 +0800 Subject: [PATCH 053/151] =?UTF-8?q?=E5=88=A0=E5=87=8F=E5=86=97=E4=BD=99?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- lib/ui/semantics/semantics_update_builder.cc | 2 -- shell/platform/ohos/platform_view_ohos_delegate.cpp | 8 -------- shell/platform/ohos/platform_view_ohos_delegate.h | 3 --- 3 files changed, 13 deletions(-) diff --git a/lib/ui/semantics/semantics_update_builder.cc b/lib/ui/semantics/semantics_update_builder.cc index 75c9a6274e..595ecf85f7 100644 --- a/lib/ui/semantics/semantics_update_builder.cc +++ b/lib/ui/semantics/semantics_update_builder.cc @@ -103,9 +103,7 @@ void SemanticsUpdateBuilder::updateNode( SkScalar scalarTransform[16]; for (int i = 0; i < 16; ++i) { scalarTransform[i] = transform.data()[i]; - FML_DLOG(INFO) << "999 node.id="<FlutterViewUpdateSemantics(buffer, strings, - // string_attribute_args); - // ax_bridge_router_->updateSemantics(buffer, strings, - // string_attribute_args); FML_DLOG(INFO) << "PlatformViewOHOSDelegate::UpdateSemantics is called"; } } diff --git a/shell/platform/ohos/platform_view_ohos_delegate.h b/shell/platform/ohos/platform_view_ohos_delegate.h index 7ad56818c0..5b5fa634f0 100644 --- a/shell/platform/ohos/platform_view_ohos_delegate.h +++ b/shell/platform/ohos/platform_view_ohos_delegate.h @@ -28,9 +28,6 @@ namespace flutter { class PlatformViewOHOSDelegate { public: -// PlatformViewOHOSDelegate() = default; -// ~PlatformViewOHOSDelegate() = default; - explicit PlatformViewOHOSDelegate( std::shared_ptr napi_facade); -- Gitee From 9c120ce228b8ae45fd856834cb4a4097cfebee80 Mon Sep 17 00:00:00 2001 From: zjxi Date: Sun, 6 Oct 2024 11:02:48 +0800 Subject: [PATCH 054/151] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 159 ++++++++++-------- .../accessibility/ohos_accessibility_bridge.h | 4 +- 2 files changed, 86 insertions(+), 77 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 5ae67c58b0..f6eb1f0069 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -79,15 +79,17 @@ void OhosAccessibilityBridge::updateSemantics( << ", " << node.childrenInTraversalOrder[i] << ")"; } - //当滑动节点产生滑动,并执行滑动处理 - if(HasScrolled(node)) { - ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); + // 当滑动节点产生滑动,并执行滑动处理 + if (HasScrolled(node)) { + ArkUI_AccessibilityElementInfo* _elementInfo = + OH_ArkUI_CreateAccessibilityElementInfo(); FlutterNodeToElementInfoById(_elementInfo, static_cast(node.id)); FlutterScrollExecution(node, _elementInfo); } - //判断是否触发liveRegion活动区,当前节点是否活跃(暂不影响正常功能) - if (node.HasFlag(FLAGS_::kIsLiveRegion)) {} + // 判断是否触发liveRegion活动区,当前节点是否活跃(暂不影响正常功能) + if (node.HasFlag(FLAGS_::kIsLiveRegion)) { + } } // TODO: 遍历更新的actions,并将所有的actions的id添加进actionMap @@ -110,9 +112,9 @@ void OhosAccessibilityBridge::updateSemantics( FML_DLOG(INFO) << "=== UpdateSemantics is end ==="; } -void OhosAccessibilityBridge::FlutterScrollExecution(flutter::SemanticsNode node, - ArkUI_AccessibilityElementInfo* elementInfoFromList) { - +void OhosAccessibilityBridge::FlutterScrollExecution( + flutter::SemanticsNode node, + ArkUI_AccessibilityElementInfo* elementInfoFromList) { double nodePosition = node.scrollPosition; double nodeScrollExtentMax = node.scrollExtentMax; double nodeScrollExtentMin = node.scrollExtentMin; @@ -137,27 +139,28 @@ void OhosAccessibilityBridge::FlutterScrollExecution(flutter::SemanticsNode node if (node.HasAction(ACTIONS_::kScrollUp) || node.HasAction(ACTIONS_::kScrollDown)) { - // TODO: ohos/arkui未提供相应的滑动属性配置event (暂未影响正常功能) } else if (node.HasAction(ACTIONS_::kScrollLeft) || - node.HasAction(ACTIONS_::kScrollRight)) { - // TODO: ohos/arkui未提供相应的滑动属性配置event (暂未影响正常功能) + node.HasAction(ACTIONS_::kScrollRight)) { } - //当可滑动组件存在滑动子节点 + // 当可滑动组件存在滑动子节点 if (node.scrollChildren > 0) { - //配置当前滑动组件的子节点总数 + // 配置当前滑动组件的子节点总数 int32_t itemCount = node.scrollChildren; - OH_ArkUI_AccessibilityElementInfoSetItemCount(elementInfoFromList, itemCount); + OH_ArkUI_AccessibilityElementInfoSetItemCount(elementInfoFromList, + itemCount); - //设置当前滑动index + // 设置当前滑动index int32_t currentItemIndex = node.scrollIndex; - OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex(elementInfoFromList, currentItemIndex); + OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex(elementInfoFromList, + currentItemIndex); - //设置当前页面可见的起始滑动index + // 设置当前页面可见的起始滑动index int32_t startItemIndex = node.scrollIndex; - OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, startItemIndex); + OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, + startItemIndex); - //计算当前滑动位置页面的可见子滑动节点数量 + // 计算当前滑动位置页面的可见子滑动节点数量 int visibleChildren = 0; // handle hidden children at the beginning and end of the list. for (const auto& childId : node.childrenInHitTestOrder) { @@ -166,30 +169,35 @@ void OhosAccessibilityBridge::FlutterScrollExecution(flutter::SemanticsNode node visibleChildren += 1; } } - //当可见滑动子节点数量超过滑动组件总子节点数量 + // 当可见滑动子节点数量超过滑动组件总子节点数量 if (node.scrollIndex + visibleChildren > node.scrollChildren) { - FML_DLOG(ERROR) << "FlutterScrollExecution -> Scroll index is out of bounds"; + FML_DLOG(ERROR) + << "FlutterScrollExecution -> Scroll index is out of bounds"; } - //当滑动击中子节点数量为0 + // 当滑动击中子节点数量为0 if (!node.childrenInHitTestOrder.size()) { - FML_DLOG(ERROR) << "FlutterScrollExecution -> Had scrollChildren but no childrenInHitTestOrder"; + FML_DLOG(ERROR) << "FlutterScrollExecution -> Had scrollChildren but no " + "childrenInHitTestOrder"; } - //设置当前页面可见的末尾滑动index + // 设置当前页面可见的末尾滑动index int32_t endItemIndex = node.scrollIndex + visibleChildren - 1; - OH_ArkUI_AccessibilityElementInfoSetEndItemIndex(elementInfoFromList, endItemIndex); - + OH_ArkUI_AccessibilityElementInfoSetEndItemIndex(elementInfoFromList, + endItemIndex); } - //发送相应的事件到arkui无障碍子系统 - Flutter_SendAccessibilityAsyncEvent(static_cast(node.id), - ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED); + // 发送相应的事件到arkui无障碍子系统 + Flutter_SendAccessibilityAsyncEvent( + static_cast(node.id), + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED); } /** - * extent common struct SemanticsNode to + * extent common struct SemanticsNode to * derived struct SemanticsNodeExtent */ -SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent(flutter::SemanticsNode node) { +SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent( + flutter::SemanticsNode node) { SemanticsNodeExtent nodeEx = SemanticsNodeExtent(); nodeEx.id = std::move(node.id); nodeEx.flags = std::move(node.flags); @@ -223,7 +231,8 @@ SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent(flutte nodeEx.transform = std::move(node.transform); nodeEx.childrenInTraversalOrder = std::move(node.childrenInTraversalOrder); nodeEx.childrenInHitTestOrder = std::move(node.childrenInHitTestOrder); - nodeEx.customAccessibilityActions = std::move(node.customAccessibilityActions); + nodeEx.customAccessibilityActions = + std::move(node.customAccessibilityActions); return nodeEx; } @@ -231,18 +240,19 @@ SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent(flutte /** * 判断当前节点是否已经滑动 */ -bool OhosAccessibilityBridge::HasScrolled(const flutter::SemanticsNode& flutterNode) { - return flutterNode.scrollPosition != std::nan(""); +bool OhosAccessibilityBridge::HasScrolled( + const flutter::SemanticsNode& flutterNode) { + return flutterNode.scrollPosition != std::nan(""); } /** * 判断是否可滑动 */ bool OhosAccessibilityBridge::IsNodeScrollable( flutter::SemanticsNode flutterNode) { - return flutterNode.HasAction(ACTIONS_::kScrollLeft) - || flutterNode.HasAction(ACTIONS_::kScrollRight) - || flutterNode.HasAction(ACTIONS_::kScrollUp) - || flutterNode.HasAction(ACTIONS_::kScrollDown); + return flutterNode.HasAction(ACTIONS_::kScrollLeft) || + flutterNode.HasAction(ACTIONS_::kScrollRight) || + flutterNode.HasAction(ACTIONS_::kScrollUp) || + flutterNode.HasAction(ACTIONS_::kScrollDown); } /** * 判断当前节点组件是否是滑动组件,如: listview, gridview等 @@ -442,7 +452,7 @@ OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) { * flutter无障碍语义树的子节点相对坐标系转化为屏幕绝对坐标的映射算法 * TODO: 当前算法流程为初期版本,需要完善优化(目前暂未考虑旋转、透视场景) */ -void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( +void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( flutter::SemanticsNode currNode) { // 获取当前flutter节点的相对rect auto currLeft = static_cast(currNode.rect.fLeft); @@ -474,7 +484,7 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( auto realParentRight = _rectPairs.second.first; auto realParentBottom = _rectPairs.second.second; - //获取root节点的绝对坐标 + // 获取root节点的绝对坐标 auto _rootRect = GetAbsoluteScreenRect(0); auto rootRight = _rootRect.second.first; auto rootBottom = _rootRect.second.second; @@ -507,7 +517,8 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( * newRight = (currLeft + _kMTransX + currRight) * realScaleFactor; * newBottom = (currTop + _kMTransY + currBottom) * realScaleFactor; */ - // 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 (增强版本) + // 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 + // (增强版本) newLeft = (currLeft + _kMTransX) * realScaleFactor + realParentLeft; newTop = (currTop + _kMTransY) * realScaleFactor + realParentTop; newRight = @@ -516,22 +527,22 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToSceenRect( (currTop + _kMTransY + currBottom) * realScaleFactor + realParentTop; } - //若子节点rect超过父节点则跳过显示(单个屏幕显示不下,滑动再重新显示) + // 若子节点rect超过父节点则跳过显示(单个屏幕显示不下,滑动再重新显示) if (newLeft < realParentLeft || newTop < realParentTop || - newRight > realParentRight || newBottom > realParentBottom || - newLeft >= newRight || newTop >= newBottom) { - FML_DLOG(ERROR) << "ConvertChildRelativeRectToSceenRect childRect is " - "bigger than parentRect -> { nodeId: " - << currNode.id << ", (" << newLeft << ", " << newTop << ", " - << newRight << ", " << newBottom << ")}"; - SetAbsoluteScreenRect(currNode.id, newLeft, realParentTop-rootRight, realParentRight, realParentBottom-rootBottom); + newRight > realParentRight || newBottom > realParentBottom || + newLeft >= newRight || newTop >= newBottom) { + FML_DLOG(ERROR) << "ConvertChildRelativeRectToScreenRect childRect is " + "bigger than parentRect -> { nodeId: " + << currNode.id << ", (" << newLeft << ", " << newTop + << ", " << newRight << ", " << newBottom << ")}"; + SetAbsoluteScreenRect(currNode.id, newLeft, realParentTop - rootRight, + realParentRight, realParentBottom - rootBottom); } else { SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); } - } - FML_DLOG(INFO) << "ConvertChildRelativeRectToSceenRect -> { nodeId: " + FML_DLOG(INFO) << "ConvertChildRelativeRectToScreenRect -> { nodeId: " << currNode.id << ", (" << newLeft << ", " << newTop << ", " << newRight << ", " << newBottom << ")}"; } @@ -584,7 +595,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( elementInfoFromList, flutterNode.label.empty() ? flutterNode.hint.c_str() - : flutterNode.label.c_str()); + : flutterNode.label.c_str()); OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes"); OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, @@ -620,7 +631,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( /** NOTE: when elementId >= 1 */ FML_DLOG(INFO) << "FlutterNodeToElementInfoById elementId = " << elementId; - //根据flutter节点信息配置elementinfo无障碍属性 + // 根据flutter节点信息配置elementinfo无障碍属性 FlutterSetElementInfoProperties(elementInfoFromList, elementId); FML_DLOG(INFO) @@ -630,18 +641,19 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( /** * 根据flutter节点信息配置elementinfo无障碍属性 */ -void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_AccessibilityElementInfo* elementInfoFromList, - int64_t elementId) { +void OhosAccessibilityBridge::FlutterSetElementInfoProperties( + ArkUI_AccessibilityElementInfo* elementInfoFromList, + int64_t elementId) { flutter::SemanticsNode flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); - //set elementinfo id + // set elementinfo id OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, flutterNode.id); - //convert relative rect to absolute rect - ConvertChildRelativeRectToSceenRect(flutterNode); + // convert relative rect to absolute rect + ConvertChildRelativeRectToScreenRect(flutterNode); auto rectPairs = GetAbsoluteScreenRect(flutterNode.id); - //set screen rect in xcomponent + // set screen rect in xcomponent int32_t left = rectPairs.first.first; int32_t top = rectPairs.first.second; int32_t right = rectPairs.second.first; @@ -652,7 +664,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_Accessibilit << flutterNode.id << " SceenRect = (" << left << ", " << top << ", " << right << ", " << bottom << ")"; - // if node is a textfield + // if node is a textfield if (IsTextField(flutterNode)) { // set elementinfo action types int32_t actionTypeNum = 10; @@ -701,9 +713,8 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_Accessibilit OH_ArkUI_AccessibilityElementInfoSetOperationActions( elementInfoFromList, actionTypeNum, actions); - } else if (IsScrollableWidget(flutterNode) - || IsNodeScrollable(flutterNode)) { - //if node is a scrollable component + } else if (IsScrollableWidget(flutterNode) || IsNodeScrollable(flutterNode)) { + // if node is a scrollable component int32_t actionTypeNum = 5; ArkUI_AccessibleAction actions[actionTypeNum]; @@ -731,7 +742,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_Accessibilit elementInfoFromList, actionTypeNum, actions); } else { - // set common component action types + // set common component action types int32_t actionTypeNum = 3; ArkUI_AccessibleAction actions[actionTypeNum]; @@ -751,7 +762,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_Accessibilit elementInfoFromList, actionTypeNum, actions); } - //set current elementinfo parent id + // set current elementinfo parent id int32_t parentId = GetParentId(elementId); if (parentId < 0) { FML_DLOG(ERROR) @@ -763,7 +774,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_Accessibilit FML_DLOG(INFO) << "FlutterNodeToElementInfoById GetParentId = " << parentId; } - //set accessibility text for announcing + // set accessibility text for announcing std::string text = flutterNode.label; OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfoFromList, text.c_str()); @@ -774,7 +785,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_Accessibilit OH_ArkUI_AccessibilityElementInfoSetHintText(elementInfoFromList, hint.c_str()); - //set chidren elementinfo ids + // set chidren elementinfo ids int32_t childCount = static_cast(flutterNode.childrenInTraversalOrder.size()); int64_t childNodeIds[childCount]; @@ -791,7 +802,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_Accessibilit /** * 根据当前flutter节点的SemanticsFlags特性,配置对应的elmentinfo属性 */ - //判断当前节点是否可点击 + // 判断当前节点是否可点击 if (IsNodeClickable(flutterNode)) { OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id @@ -833,20 +844,20 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties(ArkUI_Accessibilit FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetSelected -> true"; } - //判断当前节点组件是否可滑动 - if(IsNodeScrollable(flutterNode)) { + // 判断当前节点组件是否可滑动 + if (IsNodeScrollable(flutterNode)) { OH_ArkUI_AccessibilityElementInfoSetScrollable(elementInfoFromList, true); FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetScrollable -> true"; } - //判断当前节点组件是否可编辑(文本输入框) - if(IsTextField(flutterNode)) { + // 判断当前节点组件是否可编辑(文本输入框) + if (IsTextField(flutterNode)) { OH_ArkUI_AccessibilityElementInfoSetEditable(elementInfoFromList, true); FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetEditable -> true"; } - if(IsSlider(flutterNode)) { - //TODO 动态改变滑动条的值 + if (IsSlider(flutterNode)) { + // TODO 动态改变滑动条的值 FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetRangeInfo -> true"; } diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index c5dd598577..845c08a495 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -21,8 +21,6 @@ #include #include #include - -#include "flutter/fml/log_level.h" #include "flutter/lib/ui/semantics/custom_accessibility_action.h" #include "flutter/lib/ui/semantics/semantics_node.h" #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_manager.h" @@ -124,7 +122,7 @@ class OhosAccessibilityBridge { int64_t elementId); int32_t GetParentId(int64_t elementId); - void ConvertChildRelativeRectToSceenRect(flutter::SemanticsNode node); + void ConvertChildRelativeRectToScreenRect(flutter::SemanticsNode node); std::pair, std::pair> GetAbsoluteScreenRect(int32_t flutterNodeId); void SetAbsoluteScreenRect(int32_t flutterNodeId, -- Gitee From b6c601b335139174fcd58020ddcec9aa6d8bf5d4 Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 9 Oct 2024 17:52:56 +0800 Subject: [PATCH 055/151] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=83=A8=E5=88=86?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=BB=86=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos/accessibility/ohos_accessibility_bridge.cpp | 12 ++++++++++-- .../ohos/accessibility/ohos_accessibility_bridge.h | 2 ++ .../src/main/ets/embedding/engine/FlutterNapi.ets | 2 +- .../engine/systemchannels/AccessibilityChannel.ets | 2 +- shell/platform/ohos/library_loader.cpp | 1 + shell/platform/ohos/platform_view_ohos.h | 1 - 6 files changed, 15 insertions(+), 5 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index f6eb1f0069..66d7d6769a 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -112,6 +112,9 @@ void OhosAccessibilityBridge::updateSemantics( FML_DLOG(INFO) << "=== UpdateSemantics is end ==="; } +/** + * flutter可滑动组件的滑动逻辑处理实现 + */ void OhosAccessibilityBridge::FlutterScrollExecution( flutter::SemanticsNode node, ArkUI_AccessibilityElementInfo* elementInfoFromList) { @@ -119,6 +122,7 @@ void OhosAccessibilityBridge::FlutterScrollExecution( double nodeScrollExtentMax = node.scrollExtentMax; double nodeScrollExtentMin = node.scrollExtentMin; double infinity = std::numeric_limits::infinity(); + // 设置flutter可滑动的最大范围值 if (nodeScrollExtentMax == infinity) { nodeScrollExtentMax = SCROLL_EXTENT_FOR_INFINITY; @@ -509,6 +513,7 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( newTop = realParentTop; newRight = realParentRight; newBottom = realParentBottom; + } else { /** * 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 (初期版本) @@ -535,8 +540,11 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( "bigger than parentRect -> { nodeId: " << currNode.id << ", (" << newLeft << ", " << newTop << ", " << newRight << ", " << newBottom << ")}"; - SetAbsoluteScreenRect(currNode.id, newLeft, realParentTop - rootRight, - realParentRight, realParentBottom - rootBottom); + // 防止溢出屏幕坐标 + newTop = realParentTop - rootRight; + newBottom = realParentBottom - rootBottom; + SetAbsoluteScreenRect(currNode.id, newLeft, newTop, realParentRight, + newBottom); } else { SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 845c08a495..f86be8a37e 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -143,6 +143,8 @@ class OhosAccessibilityBridge { static const int32_t ROOT_NODE_ID = 0; constexpr static const double SCROLL_EXTENT_FOR_INFINITY = 100000.0; constexpr static const double SCROLL_POSITION_CAP_FOR_INFINITY = 70000.0; + int32_t accessibilityFeatureFlags = 0; + flutter::SemanticsNode inputFocusedNode; flutter::SemanticsNode lastInputFocusedNode; flutter::SemanticsNode accessibilityFocusedNode; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index f1488607bc..54eaf0f114 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -320,7 +320,7 @@ export default class FlutterNapi { } } - setSemanticsEnabled2(enabled: boolean, responseId: number): void { + setSemanticsEnabledWithRespId(enabled: boolean, responseId: number): void { this.ensureRunningOnMainThread(); if (this.isAttached()) { flutter.nativeSetSemanticsEnabled(this.nativeShellHolderId!, enabled); diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets index 6a9aa7d3a9..bbc5a658ea 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets @@ -94,7 +94,7 @@ export default class AccessibilityChannel implements MessageHandler{ onOhosAccessibilityEnabled(): void { let replyId: number = this.nextReplyId++; - this.flutterNapi.setSemanticsEnabled2(true, replyId); + this.flutterNapi.setSemanticsEnabledWithRespId(true, replyId); Log.i(AccessibilityChannel.TAG, "onOhosAccessibilityEnabled = true"); } diff --git a/shell/platform/ohos/library_loader.cpp b/shell/platform/ohos/library_loader.cpp index 3b6744d3b1..c414ff1c99 100644 --- a/shell/platform/ohos/library_loader.cpp +++ b/shell/platform/ohos/library_loader.cpp @@ -154,6 +154,7 @@ static napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_FUNCTION( "nativeGetShellHolderId", flutter::PlatformViewOHOSNapi::nativeGetShellHolderId), + DECLARE_NAPI_FUNCTION( "nativeDecodeUtf8", flutter::PlatformViewOHOSNapi::nativeDecodeUtf8), DECLARE_NAPI_FUNCTION( diff --git a/shell/platform/ohos/platform_view_ohos.h b/shell/platform/ohos/platform_view_ohos.h index 636680c5ea..409a92d206 100644 --- a/shell/platform/ohos/platform_view_ohos.h +++ b/shell/platform/ohos/platform_view_ohos.h @@ -145,7 +145,6 @@ class PlatformViewOHOS final : public PlatformView { std::shared_ptr platform_view_ohos_delegate_; - bool isDestroyed_; std::atomic isDestroyed_; bool GetDestroyed(); -- Gitee From 733cf8ac7fc766f366f3a94702f8b11eb452e88d Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 10 Oct 2024 09:55:37 +0800 Subject: [PATCH 056/151] =?UTF-8?q?fix:=E5=88=A0=E9=99=A4=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E6=88=90=E5=91=98=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- shell/platform/ohos/accessibility/ohos_accessibility_bridge.h | 1 - 1 file changed, 1 deletion(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index f86be8a37e..09dec9177f 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -143,7 +143,6 @@ class OhosAccessibilityBridge { static const int32_t ROOT_NODE_ID = 0; constexpr static const double SCROLL_EXTENT_FOR_INFINITY = 100000.0; constexpr static const double SCROLL_POSITION_CAP_FOR_INFINITY = 70000.0; - int32_t accessibilityFeatureFlags = 0; flutter::SemanticsNode inputFocusedNode; flutter::SemanticsNode lastInputFocusedNode; -- Gitee From 6bbdad3a7fdd10b143837fbd54058c2517abc03e Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 11 Oct 2024 19:37:33 +0800 Subject: [PATCH 057/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E6=97=A0?= =?UTF-8?q?=E9=9A=9C=E7=A2=8D=E5=AD=97=E4=BD=93=E7=B2=97=E7=BB=86=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- shell/platform/ohos/BUILD.gn | 2 + .../ohos_accessibility_bridge.cpp | 12 ++-- .../accessibility/ohos_accessibility_bridge.h | 3 +- .../ohos_accessibility_features.cpp | 58 +++++++++++++++++++ .../ohos_accessibility_features.h | 43 ++++++++++++++ .../src/main/cpp/types/libflutter/index.d.ets | 3 + .../main/ets/embedding/engine/FlutterNapi.ets | 16 ++++- .../ets/embedding/ohos/FlutterAbility.ets | 9 +++ .../src/main/ets/view/AccessibilityBridge.ets | 14 +++++ shell/platform/ohos/library_loader.cpp | 3 + .../ohos/napi/platform_view_ohos_napi.cpp | 32 ++++++++++ .../ohos/napi/platform_view_ohos_napi.h | 4 ++ shell/platform/ohos/platform_view_ohos.h | 1 - 13 files changed, 189 insertions(+), 11 deletions(-) create mode 100644 shell/platform/ohos/accessibility/ohos_accessibility_features.cpp create mode 100644 shell/platform/ohos/accessibility/ohos_accessibility_features.h diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn index f10efdbb73..68bd4bca43 100644 --- a/shell/platform/ohos/BUILD.gn +++ b/shell/platform/ohos/BUILD.gn @@ -86,6 +86,7 @@ source_set("flutter_ohos_sources") { "ohos_logging.h", "platform_view_ohos_delegate.h", "./accessibility/ohos_accessibility_bridge.h", + "./accessibility/ohos_accessibility_features.h", "./accessibility/ohos_accessibility_manager.h", ] @@ -119,6 +120,7 @@ source_set("flutter_ohos_sources") { "./surface/ohos_snapshot_surface_producer.cpp", "platform_view_ohos_delegate.cpp", "./accessibility/ohos_accessibility_bridge.cpp", + "./accessibility/ohos_accessibility_features.cpp", "./accessibility/ohos_accessibility_manager.cpp", ] diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 66d7d6769a..a7b0619250 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -92,7 +92,7 @@ void OhosAccessibilityBridge::updateSemantics( } } - // TODO: 遍历更新的actions,并将所有的actions的id添加进actionMap + // 遍历更新的actions,并将所有的actions的id添加进actionMap for (const auto& item : actions) { const flutter::CustomAccessibilityAction action = item.second; GetCustomActionDebugInfo(action); @@ -454,7 +454,7 @@ OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) { /** * flutter无障碍语义树的子节点相对坐标系转化为屏幕绝对坐标的映射算法 - * TODO: 当前算法流程为初期版本,需要完善优化(目前暂未考虑旋转、透视场景) + * 目前暂未考虑旋转、透视场景,不影响屏幕朗读功能 */ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( flutter::SemanticsNode currNode) { @@ -1377,7 +1377,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: { FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: select text(" << action << ")"; - // TODO ...输入框文本选择操作 + //输入框文本选择操作 PerformSelectText(flutterNode, action, actionArguments); break; } @@ -1387,7 +1387,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: { FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: set text(" << action << ")"; - // TODO ...输入框设置文本 + // 输入框设置文本 PerformSetText(flutterNode, action, actionArguments); break; } @@ -1398,7 +1398,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: set cursor position(" << action << ")"; - // TODO ...敬请期待 + //当前os接口不支持该功能,不影响正常屏幕朗读 break; } @@ -1418,7 +1418,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( default: { /** custom semantics action */ - // TODO ...敬请期待 } } @@ -1796,5 +1795,4 @@ void OhosAccessibilityBridge::GetCustomActionDebugInfo( << customAccessibilityAction.hint; FML_DLOG(INFO) << "------------CustomAccessibilityAction--------------"; } - } // namespace flutter diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 09dec9177f..1cc5eea55b 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -23,8 +23,9 @@ #include #include "flutter/lib/ui/semantics/custom_accessibility_action.h" #include "flutter/lib/ui/semantics/semantics_node.h" -#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_manager.h" #include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" +#include "flutter/fml/mapping.h" +#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_manager.h" namespace flutter { diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp new file mode 100644 index 0000000000..caea517fee --- /dev/null +++ b/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development 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 "flutter/shell/platform/ohos/accessibility/ohos_accessibility_features.h" +#include "flutter/shell/platform/ohos/ohos_shell_holder.h" +#include "flutter/fml/logging.h" + +namespace flutter { + + OhosAccessibilityFeatures OhosAccessibilityFeatures::instance; + + OhosAccessibilityFeatures::OhosAccessibilityFeatures() {}; + OhosAccessibilityFeatures::~OhosAccessibilityFeatures() {}; + + OhosAccessibilityFeatures* OhosAccessibilityFeatures::GetInstance() { + return &OhosAccessibilityFeatures::instance; + } + + /** + * bold text for AccessibilityFeature + */ + void OhosAccessibilityFeatures::SetBoldText(double fontWeightScale, int64_t shell_holder_id) { + bool shouldBold = fontWeightScale > 1.0; + + if (shouldBold) { + accessibilityFeatureFlags |= static_cast(flutter::AccessibilityFeatureFlag::kBoldText); + FML_DLOG(INFO) << "SetBoldText -> accessibilityFeatureFlags: "<(flutter::AccessibilityFeatureFlag::kBoldText); + } + + SendAccessibilityFlags(shell_holder_id); + } + + /** + * send the accessibility flags to flutter dart sdk + */ + void OhosAccessibilityFeatures::SendAccessibilityFlags(int64_t shell_holder_id) { + auto ohos_shell_holder = reinterpret_cast(shell_holder_id); + ohos_shell_holder->GetPlatformView()->PlatformView::SetAccessibilityFeatures(accessibilityFeatureFlags); + FML_DLOG(INFO) << "SendAccessibilityFlags -> accessibilityFeatureFlags = " + << accessibilityFeatureFlags; + accessibilityFeatureFlags = 0; + } + +} \ No newline at end of file diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_features.h b/shell/platform/ohos/accessibility/ohos_accessibility_features.h new file mode 100644 index 0000000000..093e89ce11 --- /dev/null +++ b/shell/platform/ohos/accessibility/ohos_accessibility_features.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development 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 OHOS_ACCESSIBILITY_FEATURES_H +#define OHOS_ACCESSIBILITY_FEATURES_H +#include +#include "flutter/lib/ui/window/platform_configuration.h" +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" + +namespace flutter { + +class OhosAccessibilityFeatures { + public: + OhosAccessibilityFeatures(); + ~OhosAccessibilityFeatures(); + + static OhosAccessibilityFeatures* GetInstance(); + + void SetBoldText(double fontWeightScale, int64_t shell_holder_id); + void SendAccessibilityFlags(int64_t shell_holder_id); + + private: + static OhosAccessibilityFeatures instance; + + // Font weight adjustment (FontWeight.Bold - FontWeight.Normal = w700 - w400 = 300) + static const int32_t BOLD_TEXT_WEIGHT_ADJUSTMENT = 300; + int32_t accessibilityFeatureFlags = 0; +}; + +} + +#endif \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets index ac425d3dc5..0cf14a41b0 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets @@ -152,5 +152,8 @@ export const nativeAnnounce: (message: string) => void; export const nativeSetSemanticsEnabled: (nativeShellHolderId: number, enabled: boolean) => void; +export const nativeSetFontWeightScale: (nativeShellHolderId: number, fontWeightScale: number) => void; + export const nativeGetShellHolderId: (nativeShellHolderId: number) => void; + export const nativeLookupCallbackInformation: (callback: FlutterCallbackInformation, handler: number) => number; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index 54eaf0f114..2342f78b7f 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -22,7 +22,7 @@ import { FlutterCallbackInformation } from '../../view/FlutterCallbackInformatio import image from '@ohos.multimedia.image'; import { EngineLifecycleListener } from './FlutterEngine'; import { ByteBuffer } from '../../util/ByteBuffer'; -import { Action } from '../../view/AccessibilityBridge' +import { AccessibilityManager, Action } from '../../view/AccessibilityBridge' import LocalizationPlugin from '../../plugin/localization/LocalizationPlugin'; import i18n from '@ohos.i18n'; import Any from '../../plugin/common/Any'; @@ -52,8 +52,10 @@ export default class FlutterNapi { private engineLifecycleListeners = new Set(); accessibilityDelegate: AccessibilityDelegate | null = null; localizationPlugin: LocalizationPlugin | null = null; - isDisplayingFlutterUi: boolean = false; + accessibilityManager: AccessibilityManager | null = null; + + /** * 更新刷新率 * @param rate @@ -528,6 +530,16 @@ export default class FlutterNapi { } } + setFontWeightScale(fontWeightScale: number): void { + this.ensureRunningOnMainThread(); + if (this.isAttached()) { + Log.i(TAG, "setFontWeightScale: " + fontWeightScale); + flutter.nativeSetFontWeightScale(this.nativeShellHolderId!, fontWeightScale); + } else { + Log.w(TAG, "setFontWeightScale is detached !"); + } + } + } export interface AccessibilityDelegate { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets index 2955ec31e2..7a69f4e383 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets @@ -37,6 +37,7 @@ import FlutterManager from './FlutterManager'; import { FlutterView } from '../../view/FlutterView'; import ApplicationInfoLoader from '../engine/loader/ApplicationInfoLoader'; import { accessibility } from '@kit.AccessibilityKit'; +import { AccessibilityManager } from '../../view/AccessibilityBridge'; const TAG = "FlutterAbility"; const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS'; @@ -52,6 +53,7 @@ export class FlutterAbility extends UIAbility implements Host { private flutterView: FlutterView | null = null; private mainWindow?: window.Window | null; private errorManagerId:number = 0; + private accessibilityManager?: AccessibilityManager | null; getFlutterView(): FlutterView | null { return this.flutterView; @@ -117,6 +119,8 @@ export class FlutterAbility extends UIAbility implements Host { this.delegate?.getFlutterNapi()?.setSemanticsEnabled(accessibilityState); } Log.i(TAG, `accessibility isOpen state -> ${JSON.stringify(accessibilityState)}`); + + this.accessibilityManager = new AccessibilityManager(); } onDestroy() { @@ -386,6 +390,11 @@ export class FlutterAbility extends UIAbility implements Host { .setTextScaleFactor(config.fontSizeScale == undefined? 1.0 : config.fontSizeScale) .send(); //热启动生命周期内,实时监听系统设置环境改变并实时发送相应信息 + //实时获取系统字体加粗系数 + // this.accessibilityManager?.setFontWeightScale(config.fontWeightScale == undefined? 0 : config.fontWeightScale); + this.delegate?.getFlutterNapi()?.setFontWeightScale(config.fontWeightScale == undefined? 0 : config.fontWeightScale); + Log.i(TAG, 'fontWeightScale: ' + JSON.stringify(config.fontWeightScale)); + if (config.language != '') { this.getFlutterEngine()?.getLocalizationPlugin()?.sendLocaleToFlutter(); } diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets index b3972c1213..c7122f4870 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/AccessibilityBridge.ets @@ -60,6 +60,20 @@ export default class AccessibilityBridge implements AccessibilityMessageHandler } +export class AccessibilityManager { + private fontWeightScale: number | null = null; + + setFontWeightScale(fontWeightScale: number): void { + this.fontWeightScale = fontWeightScale; + Log.i(TAG, 'setFontWeightScale: ' + JSON.stringify(this.fontWeightScale)); + } + + getFontWeightScale(): number { + Log.i(TAG, 'getFontWeightScale: ' + JSON.stringify(this.fontWeightScale)); + return this.fontWeightScale!; + } +} + export enum Action { TAP = 1 << 0, LONG_PRESS = 1 << 1, diff --git a/shell/platform/ohos/library_loader.cpp b/shell/platform/ohos/library_loader.cpp index c414ff1c99..bce055b655 100644 --- a/shell/platform/ohos/library_loader.cpp +++ b/shell/platform/ohos/library_loader.cpp @@ -151,6 +151,9 @@ static napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_FUNCTION( "nativeSetSemanticsEnabled", flutter::PlatformViewOHOSNapi::nativeSetSemanticsEnabled), + DECLARE_NAPI_FUNCTION( + "nativeSetFontWeightScale", + flutter::PlatformViewOHOSNapi::nativeSetFontWeightScale), DECLARE_NAPI_FUNCTION( "nativeGetShellHolderId", flutter::PlatformViewOHOSNapi::nativeGetShellHolderId), diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index a1b83a139d..8fa5e4faa0 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1941,6 +1941,38 @@ napi_value PlatformViewOHOSNapi::nativeSetSemanticsEnabled(napi_env env, napi_ca return nullptr; } +napi_value PlatformViewOHOSNapi::nativeSetFontWeightScale(napi_env env, napi_callback_info info) { + napi_status ret; + size_t argc = 2; + napi_value args[2] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + // get param nativeShellHolderId + int64_t shell_holder; + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeSetFontWeightScale " + "napi_get_value_int64 error:" + << ret; + return nullptr; + } + //get param fontWeightScale + double fontWeightScale = 1.0; + ret = napi_get_value_double(env, args[1], &fontWeightScale); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeSetFontWeightScale " + "napi_get_value_double error:" + << ret; + return nullptr; + } + // accessibility features get the params + auto ohosAccessibilityFeatures = OhosAccessibilityFeatures::GetInstance(); + ohosAccessibilityFeatures->SetBoldText(fontWeightScale, shell_holder); + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeSetFontWeightScale -> shell_holder: " + << shell_holder + << " fontWeightScale: "<< fontWeightScale; + return nullptr; +} + napi_value PlatformViewOHOSNapi::nativeGetShellHolderId(napi_env env, napi_callback_info info) { napi_status ret; size_t argc = 1; diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h index dbbef4a80b..d985aeed1f 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.h +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -29,6 +29,7 @@ #include "flutter/shell/platform/ohos/napi_common.h" #include "napi/native_api.h" #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" +#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_features.h" // class for all c++ to call js function namespace flutter { @@ -217,6 +218,9 @@ class PlatformViewOHOSNapi { static napi_value nativeSetSemanticsEnabled( napi_env env, napi_callback_info info); + static napi_value nativeSetFontWeightScale( + napi_env env, + napi_callback_info info); static napi_value nativeGetShellHolderId( napi_env env, napi_callback_info info); diff --git a/shell/platform/ohos/platform_view_ohos.h b/shell/platform/ohos/platform_view_ohos.h index 409a92d206..dac7916885 100644 --- a/shell/platform/ohos/platform_view_ohos.h +++ b/shell/platform/ohos/platform_view_ohos.h @@ -37,7 +37,6 @@ #include "flutter/shell/platform/ohos/vsync_waiter_ohos.h" #include "flutter/shell/platform/ohos/platform_view_ohos_delegate.h" #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" - namespace flutter { class OhosSurfaceFactoryImpl : public OhosSurfaceFactory { -- Gitee From 3ef39122b2faf01ea75f1cb4c954ec01f966f08e Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 14 Oct 2024 20:34:17 +0800 Subject: [PATCH 058/151] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../flutter/src/main/ets/embedding/ohos/FlutterAbility.ets | 1 - 1 file changed, 1 deletion(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets index 7a69f4e383..688c9cc3ea 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets @@ -391,7 +391,6 @@ export class FlutterAbility extends UIAbility implements Host { .send(); //热启动生命周期内,实时监听系统设置环境改变并实时发送相应信息 //实时获取系统字体加粗系数 - // this.accessibilityManager?.setFontWeightScale(config.fontWeightScale == undefined? 0 : config.fontWeightScale); this.delegate?.getFlutterNapi()?.setFontWeightScale(config.fontWeightScale == undefined? 0 : config.fontWeightScale); Log.i(TAG, 'fontWeightScale: ' + JSON.stringify(config.fontWeightScale)); -- Gitee From c8f9d9da7b0dc1446d65fe0a2a22662760360f0d Mon Sep 17 00:00:00 2001 From: zjxi Date: Tue, 15 Oct 2024 17:27:29 +0800 Subject: [PATCH 059/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E5=B1=9E=E6=80=A7/=E7=8A=B6=E6=80=81=E5=88=A4?= =?UTF-8?q?=E6=96=AD=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 60 ++++++++++++++----- .../accessibility/ohos_accessibility_bridge.h | 2 + 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index a7b0619250..a440f12bcd 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -83,8 +83,11 @@ void OhosAccessibilityBridge::updateSemantics( if (HasScrolled(node)) { ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); + FlutterNodeToElementInfoById(_elementInfo, static_cast(node.id)); FlutterScrollExecution(node, _elementInfo); + + OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); } // 判断是否触发liveRegion活动区,当前节点是否活跃(暂不影响正常功能) @@ -864,13 +867,24 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetEditable -> true"; } + // 判断当前节点组件是否为滑动条 if (IsSlider(flutterNode)) { // TODO 动态改变滑动条的值 FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetRangeInfo -> true"; } - // 当前节点组件默认enabled - OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true); + // 判断当前节点组件是否支持长按 + if (IsNodeHasLongPress(flutterNode)) { + OH_ArkUI_AccessibilityElementInfoSetLongClickable(elementInfoFromList, true); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetLongClickable -> true"; + } + // 判断当前节点组件是否enabled + if (IsNodeEnabled(flutterNode)) { + OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetEnabled -> true"; + } // 获取当前节点的组件类型 std::string componentTypeName = GetNodeComponentType(flutterNode); @@ -887,12 +901,13 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetComponentType: " << componentTypeName; - // 无障碍重要性,用于控制某个组件是否可被无障碍辅助服务所识别。支持的值为: - // “auto”:根据组件不同会转换为“yes”或者“no”。 - // “yes”:当前组件可被无障碍辅助服务所识别。 - // “no”:当前组件不可被无障碍辅助服务所识别。 - // “no-hide-descendants”:当前组件及其所有子组件不可被无障碍辅助服务所识别。 - // 默认值:“auto” + /** + * 无障碍重要性,用于控制某个组件是否可被无障碍辅助服务所识别。支持的值为(默认值:“auto”): + * “auto”:根据组件不同会转换为“yes”或者“no” + * “yes”:当前组件可被无障碍辅助服务所识别 + * “no”:当前组件不可被无障碍辅助服务所识别 + * “no-hide-descendants”:当前组件及其所有子组件不可被无障碍辅助服务所识别 + */ OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes"); // 无障碍组,设置为true时表示该组件及其所有子组件为一整个可以选中的组件,无障碍服务将不再关注其子组件内容。默认值:false @@ -917,7 +932,8 @@ bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) { */ bool OhosAccessibilityBridge::IsNodeClickable( flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kHasCheckedState) || + return flutterNode.HasAction(ACTIONS_::kTap) || + flutterNode.HasFlag(FLAGS_::kHasCheckedState) || flutterNode.HasFlag(FLAGS_::kIsButton) || flutterNode.HasFlag(FLAGS_::kIsTextField) || flutterNode.HasFlag(FLAGS_::kIsImage) || @@ -941,14 +957,14 @@ bool OhosAccessibilityBridge::IsNodeVisible( */ bool OhosAccessibilityBridge::IsNodeCheckable( flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kHasCheckedState); + return flutterNode.HasFlag(FLAGS_::kHasCheckedState) || flutterNode.HasFlag(FLAGS_::kHasToggledState); } /** * 判断当前flutter节点组件是否checked/unchecked(checkbox、radio button) */ bool OhosAccessibilityBridge::IsNodeChecked( flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kIsChecked); + return flutterNode.HasFlag(FLAGS_::kIsChecked) || flutterNode.HasFlag(FLAGS_::kIsToggled); } /** * 判断当前flutter节点组件是否选中 @@ -965,6 +981,18 @@ bool OhosAccessibilityBridge::IsNodePassword( return flutterNode.HasFlag(FLAGS_::kIsTextField) && flutterNode.HasFlag(FLAGS_::kIsObscured); } +/** + * 判断当前flutter节点组件是否支持长按功能 + */ +bool OhosAccessibilityBridge::IsNodeHasLongPress(flutter::SemanticsNode flutterNode) { + return flutterNode.HasAction(ACTIONS_::kLongPress); +} +/** + * 判断当前flutter节点是否enabled + */ +bool OhosAccessibilityBridge::IsNodeEnabled(flutter::SemanticsNode flutterNode) { + return !flutterNode.HasFlag(FLAGS_::kHasEnabledState) || flutterNode.HasFlag(FLAGS_::kIsEnabled); +} /** * Called to obtain element information based on a specified node. @@ -1084,7 +1112,9 @@ int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( return 0; } -/** 将arkui的action类型转化为flutter的action类型 */ +/** + * 将arkui的action类型转化为flutter的action类型 + * */ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( ArkUI_Accessibility_ActionType arkui_action) { // 部分arkui操作和flutter操作的映射,其余action暂时无法适配, 这里先return 0 @@ -1329,13 +1359,13 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( if (currComponetType == "ListView") { /** Scrolled event, sent when a scrollable component experiences a * scroll event. 4096 */ - ArkUI_AccessibilityEventType scrollEventType2 = + ArkUI_AccessibilityEventType scrollBackwardEventType = ArkUI_AccessibilityEventType:: ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; - Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType2); + Flutter_SendAccessibilityAsyncEvent(elementId, scrollBackwardEventType); FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: scroll backward(" - << action << ")" << " event: scroll backward(" << scrollEventType2 + << action << ")" << " event: scroll backward(" << scrollBackwardEventType << ")"; } break; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 1cc5eea55b..019923ac86 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -179,6 +179,8 @@ class OhosAccessibilityBridge { bool IsNodeScrollable(flutter::SemanticsNode flutterNode); bool IsNodePassword(flutter::SemanticsNode flutterNode); bool IsNodeVisible(flutter::SemanticsNode flutterNode); + bool IsNodeEnabled(flutter::SemanticsNode flutterNode); + bool IsNodeHasLongPress(flutter::SemanticsNode flutterNode); bool IsTextField(flutter::SemanticsNode flutterNode); bool IsSlider(flutter::SemanticsNode flutterNode); -- Gitee From 2c5f8a3438a3c5e0b275d3d13a5e7b97b5e87916 Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 16 Oct 2024 18:06:20 +0800 Subject: [PATCH 060/151] =?UTF-8?q?fix:=E8=A7=A3=E5=86=B3=E6=BB=91?= =?UTF-8?q?=E5=8A=A8=E7=A9=BA=E8=BD=AC=E9=97=AE=E9=A2=98,=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=97=A0=E9=9A=9C=E7=A2=8D=E5=B1=8F=E5=B9=95=E6=9C=97?= =?UTF-8?q?=E8=AF=BB=E6=8C=91=E9=80=89=E9=A1=B5=E9=9D=A2=E7=BB=BF=E6=A1=86?= =?UTF-8?q?=E9=81=97=E7=95=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 156 +++++++++++++----- .../accessibility/ohos_accessibility_bridge.h | 41 ++++- .../src/main/cpp/types/libflutter/index.d.ets | 2 + .../main/ets/embedding/engine/FlutterNapi.ets | 10 ++ .../embedding/engine/dart/DartMessenger.ets | 12 +- shell/platform/ohos/library_loader.cpp | 8 +- .../ohos/napi/platform_view_ohos_napi.cpp | 21 +++ .../ohos/napi/platform_view_ohos_napi.h | 3 + 8 files changed, 201 insertions(+), 52 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index a440f12bcd..dc6f877ae1 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -34,13 +34,91 @@ OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() { } /** - * NOTE: 从dart侧传递到c++侧的flutter语义树节点更新过程 + * 当页面状态更新事件,在页面转换、切换、调整大小时发送页面状态更新事件 + */ +void OhosAccessibilityBridge::PageStateUpdate(int64_t elementId) { + ArkUI_AccessibilityEventInfo* pageUpdateEventInfo = + OH_ArkUI_CreateAccessibilityEventInfo(); + + // 2.创建的elementinfo并根据对应id的flutternode进行属性初始化 + ArkUI_AccessibilityElementInfo* _elementInfo = + OH_ArkUI_CreateAccessibilityElementInfo(); + + OH_ArkUI_AccessibilityEventSetEventType( + pageUpdateEventInfo, + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED); + FlutterNodeToElementInfoById(_elementInfo, elementId); + OH_ArkUI_AccessibilityEventSetElementInfo(pageUpdateEventInfo, + _elementInfo); + + auto callback = [](int32_t errorCode) { + FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; + }; + + if (provider_ == nullptr) { + FML_DLOG(ERROR) << "PageStateUpdate ->" + "AccessibilityProvider = nullptr"; + return; + } + OH_ArkUI_SendAccessibilityAsyncEvent(provider_, pageUpdateEventInfo, + callback); + + OH_ArkUI_DestoryAccessibilityEventInfo(pageUpdateEventInfo); + OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); + + FML_DLOG(INFO) << "PageStateUpdate is end"; +} + +/** + * 特定节点的焦点请求 (当页面更新时自动请求id=0节点获焦) + */ +void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() { + ArkUI_AccessibilityEventInfo* reqFocusEventInfo = + OH_ArkUI_CreateAccessibilityEventInfo(); + ArkUI_AccessibilityElementInfo* elementInfo = + OH_ArkUI_CreateAccessibilityElementInfo(); + + OH_ArkUI_AccessibilityEventSetEventType( + reqFocusEventInfo, + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_REQUEST_ACCESSIBILITY_FOCUS); + + int32_t requestFocusId = 4; + OH_ArkUI_AccessibilityEventSetRequestFocusId(reqFocusEventInfo, + requestFocusId); + + OH_ArkUI_AccessibilityEventSetElementInfo(reqFocusEventInfo, elementInfo); + + auto callback = [](int32_t errorCode) { + FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; + }; + + if (provider_ == nullptr) { + FML_DLOG(ERROR) << "PageStateUpdate ->" + "AccessibilityProvider = nullptr"; + return; + } + OH_ArkUI_SendAccessibilityAsyncEvent(provider_, reqFocusEventInfo, callback); + + OH_ArkUI_DestoryAccessibilityEventInfo(reqFocusEventInfo); + OH_ArkUI_DestoryAccessibilityElementInfo(elementInfo); +} + +/** + * 从dart侧传递到c++侧的flutter无障碍语义树节点更新过程 */ void OhosAccessibilityBridge::updateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { FML_DLOG(INFO) << ("OhosAccessibilityBridge::updateSemantics is called"); + // 当flutter页面更新时,自动请求id=0节点组件获焦(滑动组件除外) + if(IS_FLUTTER_NAVIGATE) { + RequestFocusWhenPageUpdate(); + IS_FLUTTER_NAVIGATE = false; + } + /** 获取并分析每个语义节点的更新属性 */ for (auto& item : update) { // 获取当前更新的节点node @@ -156,12 +234,6 @@ void OhosAccessibilityBridge::FlutterScrollExecution( int32_t itemCount = node.scrollChildren; OH_ArkUI_AccessibilityElementInfoSetItemCount(elementInfoFromList, itemCount); - - // 设置当前滑动index - int32_t currentItemIndex = node.scrollIndex; - OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex(elementInfoFromList, - currentItemIndex); - // 设置当前页面可见的起始滑动index int32_t startItemIndex = node.scrollIndex; OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, @@ -192,11 +264,6 @@ void OhosAccessibilityBridge::FlutterScrollExecution( OH_ArkUI_AccessibilityElementInfoSetEndItemIndex(elementInfoFromList, endItemIndex); } - // 发送相应的事件到arkui无障碍子系统 - Flutter_SendAccessibilityAsyncEvent( - static_cast(node.id), - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED); } /** @@ -633,9 +700,6 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root"); - OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, - "root_content"); - return; } @@ -875,9 +939,11 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( } // 判断当前节点组件是否支持长按 if (IsNodeHasLongPress(flutterNode)) { - OH_ArkUI_AccessibilityElementInfoSetLongClickable(elementInfoFromList, true); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetLongClickable -> true"; + OH_ArkUI_AccessibilityElementInfoSetLongClickable(elementInfoFromList, + true); + FML_DLOG(INFO) + << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetLongClickable -> true"; } // 判断当前节点组件是否enabled if (IsNodeEnabled(flutterNode)) { @@ -957,14 +1023,16 @@ bool OhosAccessibilityBridge::IsNodeVisible( */ bool OhosAccessibilityBridge::IsNodeCheckable( flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kHasCheckedState) || flutterNode.HasFlag(FLAGS_::kHasToggledState); + return flutterNode.HasFlag(FLAGS_::kHasCheckedState) || + flutterNode.HasFlag(FLAGS_::kHasToggledState); } /** * 判断当前flutter节点组件是否checked/unchecked(checkbox、radio button) */ bool OhosAccessibilityBridge::IsNodeChecked( flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kIsChecked) || flutterNode.HasFlag(FLAGS_::kIsToggled); + return flutterNode.HasFlag(FLAGS_::kIsChecked) || + flutterNode.HasFlag(FLAGS_::kIsToggled); } /** * 判断当前flutter节点组件是否选中 @@ -984,14 +1052,17 @@ bool OhosAccessibilityBridge::IsNodePassword( /** * 判断当前flutter节点组件是否支持长按功能 */ -bool OhosAccessibilityBridge::IsNodeHasLongPress(flutter::SemanticsNode flutterNode) { +bool OhosAccessibilityBridge::IsNodeHasLongPress( + flutter::SemanticsNode flutterNode) { return flutterNode.HasAction(ACTIONS_::kLongPress); -} +} /** * 判断当前flutter节点是否enabled */ -bool OhosAccessibilityBridge::IsNodeEnabled(flutter::SemanticsNode flutterNode) { - return !flutterNode.HasFlag(FLAGS_::kHasEnabledState) || flutterNode.HasFlag(FLAGS_::kIsEnabled); +bool OhosAccessibilityBridge::IsNodeEnabled( + flutter::SemanticsNode flutterNode) { + return !flutterNode.HasFlag(FLAGS_::kHasEnabledState) || + flutterNode.HasFlag(FLAGS_::kIsEnabled); } /** @@ -1112,12 +1183,11 @@ int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( return 0; } -/** - * 将arkui的action类型转化为flutter的action类型 - * */ +/** + * 将arkui的action类型转化为flutter的action类型 + */ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( ArkUI_Accessibility_ActionType arkui_action) { - // 部分arkui操作和flutter操作的映射,其余action暂时无法适配, 这里先return 0 switch (arkui_action) { case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: @@ -1164,7 +1234,7 @@ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( default: // TODO might not match to the valid action in arkui - return ACTIONS_::kDismiss; + return ACTIONS_::kCustomAction; } } @@ -1365,8 +1435,8 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( Flutter_SendAccessibilityAsyncEvent(elementId, scrollBackwardEventType); FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: scroll backward(" - << action << ")" << " event: scroll backward(" << scrollBackwardEventType - << ")"; + << action << ")" << " event: scroll backward(" + << scrollBackwardEventType << ")"; } break; } @@ -1407,7 +1477,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: { FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: select text(" << action << ")"; - //输入框文本选择操作 + // 输入框文本选择操作 PerformSelectText(flutterNode, action, actionArguments); break; } @@ -1428,7 +1498,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: set cursor position(" << action << ")"; - //当前os接口不支持该功能,不影响正常屏幕朗读 + // 当前os接口不支持该功能,不影响正常屏幕朗读 break; } @@ -1456,7 +1526,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( } int32_t OhosAccessibilityBridge::ClearFocusedFocusAccessibilityNode() { - // todo ... FML_DLOG(INFO) << "=== ClearFocusedFocusAccessibilityNode is end ==="; return 0; } @@ -1464,7 +1533,6 @@ int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( int64_t elementId, int32_t requestId, int32_t* index) { - // todo ... FML_DLOG(INFO) << "=== GetAccessibilityNodeCursorPosition is end ==="; return 0; } @@ -1517,8 +1585,9 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( } OH_ArkUI_SendAccessibilityAsyncEvent(provider_, eventInfo, callback); - // 7.销毁新创建的elementinfo + // 7.销毁新创建的elementinfo, eventinfo OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); + OH_ArkUI_DestoryAccessibilityEventInfo(eventInfo); FML_DLOG(INFO) << "OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent is end"; @@ -1544,6 +1613,12 @@ bool OhosAccessibilityBridge::IsNodeFocusable( if (node.actions != 0) { return true; } + if ((node.flags & FOCUSABLE_FLAGS) != 0) { + return true; + } + if ((node.actions & ~FOCUSABLE_FLAGS) != 0) { + return true; + } // Consider text nodes focusable. return !node.label.empty() || !node.value.empty() || !node.hint.empty(); } @@ -1552,20 +1627,17 @@ void OhosAccessibilityBridge::PerformSetText( flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments) { - // TODO ... - // std::string key = ""; - // char* value; - // OH_ArkUI_FindAccessibilityActionArgumentByKey() } void OhosAccessibilityBridge::PerformSelectText( flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments) { - // TODO... } -/** 获取当前flutter节点的组件类型,并映射为arkui组件 */ +/** + * 获取当前flutter节点的组件类型,并映射为arkui组件 + */ std::string OhosAccessibilityBridge::GetNodeComponentType( const flutter::SemanticsNode& node) { if (node.HasFlag(FLAGS_::kIsButton)) { diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 019923ac86..a170e4b789 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -21,11 +21,11 @@ #include #include #include +#include "flutter/fml/mapping.h" #include "flutter/lib/ui/semantics/custom_accessibility_action.h" #include "flutter/lib/ui/semantics/semantics_node.h" -#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" -#include "flutter/fml/mapping.h" #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_manager.h" +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" namespace flutter { @@ -70,6 +70,7 @@ class OhosAccessibilityBridge { static OhosAccessibilityBridge* GetInstance(); bool isOhosAccessibilityEnabled_; + bool IS_FLUTTER_NAVIGATE = false; int64_t nativeShellHolder_; ArkUI_AccessibilityProvider* provider_; @@ -134,9 +135,10 @@ class OhosAccessibilityBridge { SemanticsNodeExtent SetAndGetSemanticsNodeExtent(flutter::SemanticsNode node); - void FlutterScrollExecution(flutter::SemanticsNode node, - ArkUI_AccessibilityElementInfo* elementInfoFromList); - + void FlutterScrollExecution( + flutter::SemanticsNode node, + ArkUI_AccessibilityElementInfo* elementInfoFromList); + void ClearFlutterSemanticsCaches(); private: @@ -159,8 +161,30 @@ class OhosAccessibilityBridge { std::unordered_map actions_mp_; std::vector flutterNavigationVec_; - void FlutterSetElementInfoProperties(ArkUI_AccessibilityElementInfo* elementInfoFromList, - int64_t elementId); + static const int32_t FOCUSABLE_FLAGS = + static_cast(FLAGS_::kHasCheckedState) | + static_cast(FLAGS_::kIsChecked) | + static_cast(FLAGS_::kIsSelected) | + static_cast(FLAGS_::kIsTextField) | + static_cast(FLAGS_::kIsFocused) | + static_cast(FLAGS_::kHasEnabledState) | + static_cast(FLAGS_::kIsEnabled) | + static_cast(FLAGS_::kIsInMutuallyExclusiveGroup) | + static_cast(FLAGS_::kHasToggledState) | + static_cast(FLAGS_::kIsToggled) | + static_cast(FLAGS_::kHasToggledState) | + static_cast(FLAGS_::kIsFocusable) | + static_cast(FLAGS_::kIsSlider); + + static const int32_t SCROLLABLE_ACTIONS = + static_cast(ACTIONS_::kScrollUp) | + static_cast(ACTIONS_::kScrollDown) | + static_cast(ACTIONS_::kScrollLeft) | + static_cast(ACTIONS_::kScrollRight); + + void FlutterSetElementInfoProperties( + ArkUI_AccessibilityElementInfo* elementInfoFromList, + int64_t elementId); void FlutterTreeToArkuiTree( ArkUI_AccessibilityElementInfoList* elementInfoList); @@ -202,6 +226,9 @@ class OhosAccessibilityBridge { void GetSemanticsFlagsDebugInfo(flutter::SemanticsNode node); void GetCustomActionDebugInfo( flutter::CustomAccessibilityAction customAccessibilityAction); + + void PageStateUpdate(int64_t elementId); + void RequestFocusWhenPageUpdate(); }; } // namespace flutter diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets index 0cf14a41b0..6786bedf54 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets @@ -157,3 +157,5 @@ export const nativeSetFontWeightScale: (nativeShellHolderId: number, fontWeightS export const nativeGetShellHolderId: (nativeShellHolderId: number) => void; export const nativeLookupCallbackInformation: (callback: FlutterCallbackInformation, handler: number) => number; + +export const nativeGetFlutterNavigationAction: (isNavigate: boolean) => void; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index 2342f78b7f..e95bdfbf4b 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -540,6 +540,16 @@ export default class FlutterNapi { } } + setFlutterNavigationAction(isNavigate: boolean): void { + this.ensureRunningOnMainThread(); + if (this.isAttached()) { + Log.i(TAG, "setFlutterNavigationAction: " + isNavigate); + flutter.nativeGetFlutterNavigationAction(isNavigate); + } else { + Log.w(TAG, "setFlutterNavigationAction is detached !"); + } + } + } export interface AccessibilityDelegate { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/dart/DartMessenger.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/dart/DartMessenger.ets index d2894ebcca..83a1366589 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/dart/DartMessenger.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/dart/DartMessenger.ets @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ErrorEvent, Queue, taskpool, worker, MessageEvents } from '@kit.ArkTS'; +import { ErrorEvent, Queue, taskpool, worker, MessageEvents, JSON } from '@kit.ArkTS'; import Log from '../../../util/Log'; import { BinaryMessageHandler, BinaryMessenger, BinaryReply, TaskPriority, TaskQueue, TaskQueueOptions } from '../../../plugin/common/BinaryMessenger'; @@ -97,6 +97,11 @@ export class DartMessenger implements BinaryMessenger, PlatformMessageHandler { } finally { TraceSection.endWithId("DartMessenger#send on " + channel, traceId); } + //获取当前flutter页面是否路由跳转,并传递到native侧 + if(channel == "flutter/navigation") { + this.flutterNapi.setFlutterNavigationAction(true); + Log.d(TAG, "setFlutterNavigationAction -> '" + channel + "'"); + } } dispatchMessageToQueue(handlerInfo: HandlerInfo, message: ArrayBuffer, replyId: number): void { @@ -127,6 +132,11 @@ export class DartMessenger implements BinaryMessenger, PlatformMessageHandler { } else { this.invokeHandler(handlerInfo?.handler as BinaryMessageHandler, message, replyId); } + //获取当前flutter页面是否路由跳转,并传递到native侧 + if(channel == "flutter/navigation") { + this.flutterNapi.setFlutterNavigationAction(true); + Log.d(TAG, "setFlutterNavigationAction -> '" + channel + "'"); + } } handlePlatformMessageResponse(replyId: number, reply: ArrayBuffer): void { diff --git a/shell/platform/ohos/library_loader.cpp b/shell/platform/ohos/library_loader.cpp index bce055b655..3502372782 100644 --- a/shell/platform/ohos/library_loader.cpp +++ b/shell/platform/ohos/library_loader.cpp @@ -151,7 +151,7 @@ static napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_FUNCTION( "nativeSetSemanticsEnabled", flutter::PlatformViewOHOSNapi::nativeSetSemanticsEnabled), - DECLARE_NAPI_FUNCTION( + DECLARE_NAPI_FUNCTION( "nativeSetFontWeightScale", flutter::PlatformViewOHOSNapi::nativeSetFontWeightScale), DECLARE_NAPI_FUNCTION( @@ -160,9 +160,13 @@ static napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_FUNCTION( "nativeDecodeUtf8", flutter::PlatformViewOHOSNapi::nativeDecodeUtf8), - DECLARE_NAPI_FUNCTION( + DECLARE_NAPI_FUNCTION( "nativeLookupCallbackInformation", flutter::PlatformViewOHOSNapi::nativeLookupCallbackInformation), + DECLARE_NAPI_FUNCTION( + "nativeGetFlutterNavigationAction", + flutter::PlatformViewOHOSNapi::nativeGetFlutterNavigationAction), + }; FML_DLOG(INFO) << "Init NAPI size=" << sizeof(desc) / sizeof(desc[0]); diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index 8fa5e4faa0..b6c8d8bdd0 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -2044,4 +2044,25 @@ napi_value PlatformViewOHOSNapi::nativeLookupCallbackInformation(napi_env env, n napi_create_int32(env, 0, &result); return result; } + +napi_value PlatformViewOHOSNapi::nativeGetFlutterNavigationAction(napi_env env, napi_callback_info info) { + napi_status ret; + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + bool isNavigate; + ret = napi_get_value_bool(env, args[0], &isNavigate); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeGetFlutterNavigationAction " + "napi_get_value_bool error:" + << ret; + return nullptr; + } + + auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge->IS_FLUTTER_NAVIGATE = isNavigate; + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeGetFlutterNavigationAction -> "< Date: Wed, 16 Oct 2024 20:18:46 +0800 Subject: [PATCH 061/151] =?UTF-8?q?refactor:=E5=B0=81=E8=A3=85=E5=A4=8D?= =?UTF-8?q?=E7=94=A8ets=E4=BE=A7=E4=BB=A3=E7=A0=81=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=8C=E6=9D=BE=E8=80=A6=E5=90=88=E6=96=B9=E4=BE=BF=E6=89=A9?= =?UTF-8?q?=E5=B1=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../embedding/engine/dart/DartMessenger.ets | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/dart/DartMessenger.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/dart/DartMessenger.ets index 83a1366589..a1773db5c7 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/dart/DartMessenger.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/dart/DartMessenger.ets @@ -97,11 +97,7 @@ export class DartMessenger implements BinaryMessenger, PlatformMessageHandler { } finally { TraceSection.endWithId("DartMessenger#send on " + channel, traceId); } - //获取当前flutter页面是否路由跳转,并传递到native侧 - if(channel == "flutter/navigation") { - this.flutterNapi.setFlutterNavigationAction(true); - Log.d(TAG, "setFlutterNavigationAction -> '" + channel + "'"); - } + this.IsFlutterNavigationExecuted(channel); } dispatchMessageToQueue(handlerInfo: HandlerInfo, message: ArrayBuffer, replyId: number): void { @@ -132,11 +128,7 @@ export class DartMessenger implements BinaryMessenger, PlatformMessageHandler { } else { this.invokeHandler(handlerInfo?.handler as BinaryMessageHandler, message, replyId); } - //获取当前flutter页面是否路由跳转,并传递到native侧 - if(channel == "flutter/navigation") { - this.flutterNapi.setFlutterNavigationAction(true); - Log.d(TAG, "setFlutterNavigationAction -> '" + channel + "'"); - } + this.IsFlutterNavigationExecuted(channel); } handlePlatformMessageResponse(replyId: number, reply: ArrayBuffer): void { @@ -167,6 +159,14 @@ export class DartMessenger implements BinaryMessenger, PlatformMessageHandler { getPendingChannelResponseCount(): number { return this.pendingReplies.size; } + + //获取当前flutter页面是否路由跳转,并传递到native侧 + IsFlutterNavigationExecuted(channel: String): void { + if(channel == "flutter/navigation") { + this.flutterNapi.setFlutterNavigationAction(true); + Log.d(TAG, "setFlutterNavigationAction -> '" + channel + "'"); + } + } } /** -- Gitee From ea1352e3e7cf9ed0c89e3310053fc785d14a62f1 Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 17 Oct 2024 10:51:46 +0800 Subject: [PATCH 062/151] =?UTF-8?q?refactor:=E5=88=A0=E9=99=A4=E5=85=AC?= =?UTF-8?q?=E5=85=B1=E4=BB=A3=E7=A0=81debug=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- lib/ui/window/platform_configuration.cc | 11 ----------- runtime/runtime_controller.cc | 5 ----- shell/common/engine.cc | 4 ---- shell/common/platform_view.cc | 1 - shell/common/shell.cc | 4 ---- shell/platform/embedder/platform_view_embedder.cc | 1 - 6 files changed, 26 deletions(-) diff --git a/lib/ui/window/platform_configuration.cc b/lib/ui/window/platform_configuration.cc index 1f20776fba..07afbfd75d 100644 --- a/lib/ui/window/platform_configuration.cc +++ b/lib/ui/window/platform_configuration.cc @@ -118,9 +118,6 @@ void PlatformConfiguration::UpdateLifecycleState(const std::string& data) { void PlatformConfiguration::UpdateSemanticsEnabled(bool enabled) { std::shared_ptr dart_state = update_semantics_enabled_.dart_state().lock(); - FML_DLOG(INFO) - << "PlatformConfiguration::UpdateSemanticsEnabled is called, enabled:" - << enabled; if (!dart_state) { return; } @@ -134,9 +131,6 @@ void PlatformConfiguration::UpdateSemanticsEnabled(bool enabled) { void PlatformConfiguration::UpdateAccessibilityFeatures(int32_t values) { std::shared_ptr dart_state = update_accessibility_features_.dart_state().lock(); - FML_DLOG(INFO) - << "PlatformConfiguration::UpdateAccessibilityFeatures is called, values:" - << values; if (!dart_state) { return; } @@ -151,7 +145,6 @@ void PlatformConfiguration::DispatchPlatformMessage( std::shared_ptr dart_state = dispatch_platform_message_.dart_state().lock(); - FML_DLOG(INFO) << "DispatchPlatformMessage channel: " << message->channel(); if (!dart_state) { FML_DLOG(WARNING) << "Dropping platform message for lack of DartState on channel: " @@ -197,7 +190,6 @@ void PlatformConfiguration::DispatchSemanticsAction(int32_t id, if (Dart_IsError(args_handle)) { return; } - FML_DLOG(INFO) << "PlatformConfiguration::DispatchSemanticsAction: id=" << id<<" action="<(action); tonic::CheckAndHandleError(tonic::DartInvoke( dispatch_semantics_action_.Get(), {tonic::ToDart(id), tonic::ToDart(static_cast(action)), @@ -363,8 +355,6 @@ Dart_Handle PlatformConfigurationNativeApi::SendPortPlatformMessage( void PlatformConfigurationNativeApi::RespondToPlatformMessage( int response_id, const tonic::DartByteData& data) { - FML_DLOG(INFO) << "PlatformConfigurationNativeApi::RespondToPlatformMessage:" - << response_id; if (Dart_IsNull(data.dart_handle())) { UIDartState::Current() ->platform_configuration() @@ -424,7 +414,6 @@ void PlatformConfigurationNativeApi::UpdateSemantics(SemanticsUpdate* update) { UIDartState::ThrowIfUIOperationsProhibited(); UIDartState::Current()->platform_configuration()->client()->UpdateSemantics( update); - FML_DLOG(INFO) << "PlatformConfigurationNativeApi::UpdateSemantics is called"; } Dart_Handle PlatformConfigurationNativeApi::ComputePlatformResolvedLocale( diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index 520c6ff5c5..9870d5e780 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -175,7 +175,6 @@ bool RuntimeController::SetSemanticsEnabled(bool enabled) { if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) { platform_configuration->UpdateSemanticsEnabled( platform_data_.semantics_enabled); - FML_DLOG(INFO)<<"RuntimeController::SetSemanticsEnabled, enable="<UpdateAccessibilityFeatures( platform_data_.accessibility_feature_flags_); - FML_DLOG(INFO)<<"RuntimeController::SetAccessibilityFeatures="; return true; } @@ -286,7 +284,6 @@ bool RuntimeController::DispatchSemanticsAction(int32_t id, TRACE_EVENT1("flutter", "RuntimeController::DispatchSemanticsAction", "mode", "basic"); if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) { - FML_DLOG(INFO) << "RuntimeController::DispatchSemanticsAction, id="< id:"<(action); delegate_.OnPlatformViewDispatchSemanticsAction(id, action, std::move(args)); } diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 225e92d330..bdaf8c234d 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1005,7 +1005,6 @@ void Shell::OnPlatformViewDispatchSemanticsAction(int32_t id, fml::MakeCopyable([engine = engine_->GetWeakPtr(), id, action, args = std::move(args)]() mutable { if (engine) { - FML_DLOG(INFO) << "Shell::OnPlatformViewDispatchSemanticsAction, id="<UpdateSemantics(update, actions); } }); diff --git a/shell/platform/embedder/platform_view_embedder.cc b/shell/platform/embedder/platform_view_embedder.cc index 12c3f83dbd..1cedc22810 100644 --- a/shell/platform/embedder/platform_view_embedder.cc +++ b/shell/platform/embedder/platform_view_embedder.cc @@ -122,7 +122,6 @@ void PlatformViewEmbedder::UpdateSemantics( if (platform_dispatch_table_.update_semantics_callback != nullptr) { platform_dispatch_table_.update_semantics_callback(std::move(update), std::move(actions)); - FML_DLOG(INFO) << "PlatformViewEmbedder::UpdateSemantics is called"; } } -- Gitee From 977702bef2dbe68dad2c3e1ce6d97277907b1781 Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 17 Oct 2024 11:41:45 +0800 Subject: [PATCH 063/151] =?UTF-8?q?refactor:=E4=BF=AE=E6=94=B9ets=E9=83=A8?= =?UTF-8?q?=E5=88=86=E4=BB=A3=E7=A0=81=E7=BC=A9=E7=B4=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../flutter/src/main/ets/embedding/ohos/FlutterAbility.ets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets index 688c9cc3ea..8a336a5297 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets @@ -81,7 +81,7 @@ export class FlutterAbility extends UIAbility implements Host { this.delegate = new FlutterAbilityAndEntryDelegate(this); await this?.delegate?.onAttach(this.context); Log.i(TAG, 'onAttach end'); - this?.delegate?.platformPlugin?.setUIAbilityContext(this.context); + this?.delegate?.platformPlugin?.setUIAbilityContext(this.context); this?.delegate?.onRestoreInstanceState(want); if (this.stillAttachedForEvent("onCreate")) { -- Gitee From ddc35f64d102096f3499b5f46697e3919c44c083 Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 17 Oct 2024 20:35:15 +0800 Subject: [PATCH 064/151] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- shell/platform/ohos/napi/platform_view_ohos_napi.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index b6c8d8bdd0..f77c511b15 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1828,7 +1828,6 @@ napi_value PlatformViewOHOSNapi::nativeDecodeUtf8(napi_env env, napi_value PlatformViewOHOSNapi::nativeUpdateSemantics( napi_env env, napi_callback_info info) { - // TODO ets calls c++ return nullptr; } @@ -1836,7 +1835,6 @@ napi_value PlatformViewOHOSNapi::nativeUpdateSemantics( napi_value PlatformViewOHOSNapi::nativeUpdateCustomAccessibilityActions( napi_env env, napi_callback_info info) { - // TODO ets calls c++ return nullptr; } -- Gitee From 060009215eb20849cc4cf775e10a3a6f0289a3dc Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 18 Oct 2024 14:54:59 +0800 Subject: [PATCH 065/151] =?UTF-8?q?refactor:=E9=83=A8=E5=88=86=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E8=A1=8C=E6=95=B0=E5=A4=AA=E5=A4=9A=EF=BC=8C=E5=B0=81?= =?UTF-8?q?=E8=A3=85=E4=B8=BA=E5=85=AC=E5=85=B1=E5=87=BD=E6=95=B0=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E6=B6=88=E9=99=A4=E9=AD=94=E9=AC=BC=E6=95=B0=E5=92=8C?= =?UTF-8?q?=E4=B8=8D=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 399 +++++++++--------- .../accessibility/ohos_accessibility_bridge.h | 24 +- .../ohos/napi/platform_view_ohos_napi.cpp | 2 - .../platform/ohos/ohos_xcomponent_adapter.cpp | 54 +-- 4 files changed, 257 insertions(+), 222 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index dc6f877ae1..9eec196478 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -29,18 +29,19 @@ OhosAccessibilityBridge OhosAccessibilityBridge::bridgeInstance; OhosAccessibilityBridge::OhosAccessibilityBridge() {}; OhosAccessibilityBridge::~OhosAccessibilityBridge() {}; -OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() { +OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() +{ return &OhosAccessibilityBridge::bridgeInstance; } /** * 当页面状态更新事件,在页面转换、切换、调整大小时发送页面状态更新事件 */ -void OhosAccessibilityBridge::PageStateUpdate(int64_t elementId) { +void OhosAccessibilityBridge::PageStateUpdate(int64_t elementId) +{ ArkUI_AccessibilityEventInfo* pageUpdateEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); - // 2.创建的elementinfo并根据对应id的flutternode进行属性初始化 ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); @@ -73,7 +74,8 @@ void OhosAccessibilityBridge::PageStateUpdate(int64_t elementId) { /** * 特定节点的焦点请求 (当页面更新时自动请求id=0节点获焦) */ -void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() { +void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() +{ ArkUI_AccessibilityEventInfo* reqFocusEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); ArkUI_AccessibilityElementInfo* elementInfo = @@ -110,14 +112,15 @@ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() { */ void OhosAccessibilityBridge::updateSemantics( flutter::SemanticsNodeUpdates update, - flutter::CustomAccessibilityActionUpdates actions) { + flutter::CustomAccessibilityActionUpdates actions) +{ FML_DLOG(INFO) << ("OhosAccessibilityBridge::updateSemantics is called"); // 当flutter页面更新时,自动请求id=0节点组件获焦(滑动组件除外) - if(IS_FLUTTER_NAVIGATE) { - RequestFocusWhenPageUpdate(); - IS_FLUTTER_NAVIGATE = false; - } + if(IS_FLUTTER_NAVIGATE) { + RequestFocusWhenPageUpdate(); + IS_FLUTTER_NAVIGATE = false; + } /** 获取并分析每个语义节点的更新属性 */ for (auto& item : update) { @@ -170,6 +173,8 @@ void OhosAccessibilityBridge::updateSemantics( // 判断是否触发liveRegion活动区,当前节点是否活跃(暂不影响正常功能) if (node.HasFlag(FLAGS_::kIsLiveRegion)) { + FML_DLOG(INFO) << "UpdateSemantics -> flutterNode is kIsLiveRegion, node.id=" + << node.id; } } @@ -198,7 +203,8 @@ void OhosAccessibilityBridge::updateSemantics( */ void OhosAccessibilityBridge::FlutterScrollExecution( flutter::SemanticsNode node, - ArkUI_AccessibilityElementInfo* elementInfoFromList) { + ArkUI_AccessibilityElementInfo* elementInfoFromList) +{ double nodePosition = node.scrollPosition; double nodeScrollExtentMax = node.scrollExtentMax; double nodeScrollExtentMin = node.scrollExtentMin; @@ -271,7 +277,8 @@ void OhosAccessibilityBridge::FlutterScrollExecution( * derived struct SemanticsNodeExtent */ SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent( - flutter::SemanticsNode node) { + flutter::SemanticsNode node) +{ SemanticsNodeExtent nodeEx = SemanticsNodeExtent(); nodeEx.id = std::move(node.id); nodeEx.flags = std::move(node.flags); @@ -315,14 +322,16 @@ SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent( * 判断当前节点是否已经滑动 */ bool OhosAccessibilityBridge::HasScrolled( - const flutter::SemanticsNode& flutterNode) { + const flutter::SemanticsNode& flutterNode) +{ return flutterNode.scrollPosition != std::nan(""); } /** * 判断是否可滑动 */ bool OhosAccessibilityBridge::IsNodeScrollable( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasAction(ACTIONS_::kScrollLeft) || flutterNode.HasAction(ACTIONS_::kScrollRight) || flutterNode.HasAction(ACTIONS_::kScrollUp) || @@ -332,14 +341,16 @@ bool OhosAccessibilityBridge::IsNodeScrollable( * 判断当前节点组件是否是滑动组件,如: listview, gridview等 */ bool OhosAccessibilityBridge::IsScrollableWidget( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); } /** * 主动播报特定文本 */ -void OhosAccessibilityBridge::announce(std::unique_ptr& message) { +void OhosAccessibilityBridge::announce(std::unique_ptr& message) +{ // 创建并设置屏幕朗读事件 ArkUI_AccessibilityEventInfo* announceEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); @@ -369,7 +380,8 @@ void OhosAccessibilityBridge::announce(std::unique_ptr& message) { * 根据nodeid获取或创建flutter语义节点 */ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode( - int32_t id) { + int32_t id) +{ flutter::SemanticsNode node; if (flutterSemanticsTree_.count(id) > 0) { return flutterSemanticsTree_.at(id); @@ -385,7 +397,8 @@ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode( * flutter的语义节点初始化配置给arkui创建的elementInfos */ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( - ArkUI_AccessibilityElementInfoList* elementInfoList) { + ArkUI_AccessibilityElementInfoList* elementInfoList) +{ if (flutterSemanticsTree_.size() == 0) { FML_DLOG(ERROR) << "OhosAccessibilityBridge::FlutterTreeToArkuiTree " "flutterSemanticsTree_.size() = 0"; @@ -412,19 +425,8 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfo, &rect); // 设置elementinfo的action类型 - int32_t actionTypeNum = 3; - ArkUI_AccessibleAction actions[actionTypeNum]; - actions[0].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; - actions[0].description = "获取焦点动作事件"; - actions[1].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; - actions[1].description = "清除焦点动作事件"; - actions[2].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; - actions[2].description = "点击动作事件"; - OH_ArkUI_AccessibilityElementInfoSetOperationActions( - elementInfo, actionTypeNum, actions); + std::string widget_type = GetNodeComponentType(flutterNode); + FlutterSetElementInfoOperationActions(elementInfo, widget_type); // 设置elementid OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfo, flutterNode.id); @@ -434,7 +436,6 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( if (flutterNode.id == 0) { OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, -2100000); FML_DLOG(INFO) << "FlutterTreeToArkuiTree parent.id= " << parentId; - } else { OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, parentId); FML_DLOG(INFO) << "FlutterTreeToArkuiTree parent.id= " << parentId; @@ -481,7 +482,8 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( /** * 获取当前elementid的父节点id */ -int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) { +int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) +{ int32_t childElementId = static_cast(elementId); if (!parentChildIdVec.size()) { FML_DLOG(INFO) @@ -503,7 +505,8 @@ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, float left, float top, float right, - float bottom) { + float bottom) +{ screenRectMap_[flutterNodeId] = std::make_pair(std::make_pair(left, top), std::make_pair(right, bottom)); FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId @@ -527,7 +530,8 @@ OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) { * 目前暂未考虑旋转、透视场景,不影响屏幕朗读功能 */ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( - flutter::SemanticsNode currNode) { + flutter::SemanticsNode currNode) +{ // 获取当前flutter节点的相对rect auto currLeft = static_cast(currNode.rect.fLeft); auto currTop = static_cast(currNode.rect.fTop); @@ -575,7 +579,6 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( newBottom = currBottom * _kMScaleY; // 更新当前flutter节点currNode的相对坐标 -> 屏幕绝对坐标 SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); - } else { // 若当前节点的相对坐标与父亲节点的相对坐标值相同,则直接继承坐标值 if (currRight == parentRight && currBottom == parentBottom) { @@ -583,7 +586,6 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( newTop = realParentTop; newRight = realParentRight; newBottom = realParentBottom; - } else { /** * 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 (初期版本) @@ -615,7 +617,6 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( newBottom = realParentBottom - rootBottom; SetAbsoluteScreenRect(currNode.id, newLeft, newTop, realParentRight, newBottom); - } else { SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); } @@ -630,7 +631,8 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( */ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( ArkUI_AccessibilityElementInfo* elementInfoFromList, - int64_t elementId) { + int64_t elementId) +{ if (elementInfoFromList == nullptr) { FML_DLOG(INFO) << "OhosAccessibilityBridge::FlutterNodeToElementInfoById " "elementInfoFromList is null"; @@ -654,16 +656,8 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( SetAbsoluteScreenRect(0, left, top, right, bottom); // 设置elementinfo的action类型 - int32_t actionTypeNum = 2; - ArkUI_AccessibleAction actions[actionTypeNum]; - actions[0].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; - actions[0].description = "获取焦点动作事件"; - actions[1].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; - actions[1].description = "清空焦点动作事件"; - OH_ArkUI_AccessibilityElementInfoSetOperationActions( - elementInfoFromList, actionTypeNum, actions); + std::string widget_type = "root"; + FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); // 根据flutternode信息配置对应的elementinfo OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, 0); @@ -693,7 +687,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds); - // 配置常用属性 + // 配置root节点常用属性 OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true); @@ -713,12 +707,88 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( << "=== OhosAccessibilityBridge::FlutterNodeToElementInfoById is end ==="; } +/** + * 判断源字符串是否包含目标字符串 + */ +bool OhosAccessibilityBridge::Contains(const std::string& source, const std::string& target) +{ + return source.find(target) != std::string::npos; +} + +/** + * 配置arkui节点的可操作动作类型 + */ +void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( + ArkUI_AccessibilityElementInfo* elementInfoFromList, + std::string widget_type) +{ + //计算不同组件类型的action类型数组数量 + int32_t actionTypeNum = 0; + if (widget_type == "textfield") { + for (const auto action_item: ArkUI_ACTION_TYPE_MAP_) { + std::string action_description= action_item.first; + if (Contains(action_description, "focus")) { actionTypeNum++; }; + if (Contains(action_description, "click")) { actionTypeNum++; }; + if (Contains(action_description, "text")) { actionTypeNum++; }; + if (Contains(action_description, "press")) { actionTypeNum++; }; + } + } else if (widget_type == "scrollable") { + for (const auto action_item: ArkUI_ACTION_TYPE_MAP_) { + std::string action_description= action_item.first; + if (Contains(action_description, "focus")) { actionTypeNum++; }; + if (Contains(action_description, "click")) { actionTypeNum++; }; + if (Contains(action_description, "scroll")) { actionTypeNum++; }; + } + } else { + for (const auto action_item: ArkUI_ACTION_TYPE_MAP_) { + std::string action_description= action_item.first; + if (Contains(action_description, "focus")) { actionTypeNum++; }; + if (Contains(action_description, "click")) { actionTypeNum++; }; + } + } + //配置相应组件的action操作属性 + ArkUI_AccessibleAction actions[actionTypeNum]; + int32_t count = 0; + for (const auto item: ArkUI_ACTION_TYPE_MAP_) { + std::string description = item.first; + if (widget_type == "textfield") { + //textfield组件类型包含focus, text, click, long press动作类型 + if (Contains(description, "focus") || + Contains(description, "click") || + Contains(description, "text") || + Contains(description, "press")) { + actions[count++].actionType = item.second; + actions[count-1].description = description.c_str(); + } + } else if (widget_type == "scrollable") { + //可滑动组件类型包含focus, scroll, click动作类型 + if (Contains(description, "focus") || + Contains(description, "click") || + Contains(description, "scroll")) { + actions[count++].actionType = item.second; + actions[count-1].description = description.c_str(); + } + } else { + //通用组件包含点击、获焦、失焦 + if (Contains(description, "focus") || + Contains(description, "click")) { + actions[count++].actionType = item.second; + actions[count-1].description = description.c_str(); + } + } + } + //set elementinfo OperationActions + OH_ArkUI_AccessibilityElementInfoSetOperationActions( + elementInfoFromList, actionTypeNum, actions); +} + /** * 根据flutter节点信息配置elementinfo无障碍属性 */ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( ArkUI_AccessibilityElementInfo* elementInfoFromList, - int64_t elementId) { + int64_t elementId) +{ flutter::SemanticsNode flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); @@ -739,102 +809,19 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( << flutterNode.id << " SceenRect = (" << left << ", " << top << ", " << right << ", " << bottom << ")"; - // if node is a textfield + //配置arkui的elementinfo可操作动作属性 if (IsTextField(flutterNode)) { - // set elementinfo action types - int32_t actionTypeNum = 10; - ArkUI_AccessibleAction actions[actionTypeNum]; - - actions[0].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; - actions[0].description = "获取焦点"; - - actions[1].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; - actions[1].description = "清除焦点"; - - actions[2].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; - actions[2].description = "点击操作"; - - actions[3].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK; - actions[3].description = "长按操作"; - - actions[4].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY; - actions[4].description = "文本复制"; - - actions[5].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE; - actions[5].description = "文本粘贴"; - - actions[6].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT; - actions[6].description = "文本剪切"; - - actions[7].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT; - actions[7].description = "文本选择"; - - actions[8].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT; - actions[8].description = "文本内容设置"; - - actions[9].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION; - actions[9].description = "光标位置设置"; - - OH_ArkUI_AccessibilityElementInfoSetOperationActions( - elementInfoFromList, actionTypeNum, actions); - + //若当前flutter节点为文本输入框组件 + std::string widget_type = "textfield"; + FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); } else if (IsScrollableWidget(flutterNode) || IsNodeScrollable(flutterNode)) { - // if node is a scrollable component - int32_t actionTypeNum = 5; - ArkUI_AccessibleAction actions[actionTypeNum]; - - actions[0].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; - actions[0].description = "获取焦点"; - - actions[1].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; - actions[1].description = "清除焦点"; - - actions[2].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; - actions[2].description = "点击动作"; - - actions[3].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD; - actions[3].description = "向上滑动"; - - actions[4].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD; - actions[4].description = "向下滑动"; - - OH_ArkUI_AccessibilityElementInfoSetOperationActions( - elementInfoFromList, actionTypeNum, actions); - + //若当前flutter节点为可滑动组件类型 + std::string widget_type = "scrollable"; + FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); } else { - // set common component action types - int32_t actionTypeNum = 3; - ArkUI_AccessibleAction actions[actionTypeNum]; - - actions[0].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; - actions[0].description = "获取焦点"; - - actions[1].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; - actions[1].description = "清除焦点"; - - actions[2].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; - actions[2].description = "点击动作"; - - OH_ArkUI_AccessibilityElementInfoSetOperationActions( - elementInfoFromList, actionTypeNum, actions); + //若当前flutter节点为通用组件 + std::string widget_type = "common"; + FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); } // set current elementinfo parent id @@ -933,7 +920,6 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( } // 判断当前节点组件是否为滑动条 if (IsSlider(flutterNode)) { - // TODO 动态改变滑动条的值 FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetRangeInfo -> true"; } @@ -984,20 +970,23 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( /** * 判断当前节点是否为textfield文本框 */ -bool OhosAccessibilityBridge::IsTextField(flutter::SemanticsNode flutterNode) { +bool OhosAccessibilityBridge::IsTextField(flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kIsTextField); } /** * 判断当前节点是否为滑动条slider类型 */ -bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) { +bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kIsSlider); } /** * 判断当前flutter节点组件是否可点击 */ bool OhosAccessibilityBridge::IsNodeClickable( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasAction(ACTIONS_::kTap) || flutterNode.HasFlag(FLAGS_::kHasCheckedState) || flutterNode.HasFlag(FLAGS_::kIsButton) || @@ -1015,14 +1004,16 @@ bool OhosAccessibilityBridge::IsNodeClickable( * 判断当前flutter节点组件是否可显示 */ bool OhosAccessibilityBridge::IsNodeVisible( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kIsHidden) ? false : true; } /** * 判断当前flutter节点组件是否具备checkable属性 */ bool OhosAccessibilityBridge::IsNodeCheckable( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kHasCheckedState) || flutterNode.HasFlag(FLAGS_::kHasToggledState); } @@ -1030,7 +1021,8 @@ bool OhosAccessibilityBridge::IsNodeCheckable( * 判断当前flutter节点组件是否checked/unchecked(checkbox、radio button) */ bool OhosAccessibilityBridge::IsNodeChecked( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kIsChecked) || flutterNode.HasFlag(FLAGS_::kIsToggled); } @@ -1038,7 +1030,8 @@ bool OhosAccessibilityBridge::IsNodeChecked( * 判断当前flutter节点组件是否选中 */ bool OhosAccessibilityBridge::IsNodeSelected( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kIsSelected); } /** @@ -1053,14 +1046,16 @@ bool OhosAccessibilityBridge::IsNodePassword( * 判断当前flutter节点组件是否支持长按功能 */ bool OhosAccessibilityBridge::IsNodeHasLongPress( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasAction(ACTIONS_::kLongPress); } /** * 判断当前flutter节点是否enabled */ bool OhosAccessibilityBridge::IsNodeEnabled( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return !flutterNode.HasFlag(FLAGS_::kHasEnabledState) || flutterNode.HasFlag(FLAGS_::kIsEnabled); } @@ -1073,7 +1068,8 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( int64_t elementId, ArkUI_AccessibilitySearchMode mode, int32_t requestId, - ArkUI_AccessibilityElementInfoList* elementList) { + ArkUI_AccessibilityElementInfoList* elementList) +{ FML_DLOG(INFO) << "#### FindAccessibilityNodeInfosById input-params ####: elementId = " << elementId << " mode=" << mode << " requestId=" << requestId @@ -1158,8 +1154,8 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosByText( int64_t elementId, const char* text, int32_t requestId, - ArkUI_AccessibilityElementInfoList* elementList) { - // TODO + ArkUI_AccessibilityElementInfoList* elementList) +{ FML_DLOG(INFO) << "=== FindAccessibilityNodeInfosByText is end ==="; return 0; } @@ -1167,8 +1163,8 @@ int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( int64_t elementId, ArkUI_AccessibilityFocusType focusType, int32_t requestId, - ArkUI_AccessibilityElementInfo* elementinfo) { - // TODO + ArkUI_AccessibilityElementInfo* elementinfo) +{ FML_DLOG(INFO) << "=== FindFocusedAccessibilityNode is end ==="; return 0; @@ -1177,17 +1173,32 @@ int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( int64_t elementId, ArkUI_AccessibilityFocusMoveDirection direction, int32_t requestId, - ArkUI_AccessibilityElementInfo* elementList) { - // TODO + ArkUI_AccessibilityElementInfo* elementList) +{ FML_DLOG(INFO) << "=== FindNextFocusAccessibilityNode is end ==="; return 0; } +int32_t OhosAccessibilityBridge::ClearFocusedFocusAccessibilityNode() +{ + FML_DLOG(INFO) << "=== ClearFocusedFocusAccessibilityNode is end ==="; + return 0; +} +int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( + int64_t elementId, + int32_t requestId, + int32_t* index) +{ + FML_DLOG(INFO) << "=== GetAccessibilityNodeCursorPosition is end ==="; + return 0; +} + /** * 将arkui的action类型转化为flutter的action类型 */ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( - ArkUI_Accessibility_ActionType arkui_action) { + ArkUI_Accessibility_ActionType arkui_action) +{ switch (arkui_action) { case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: @@ -1233,7 +1244,7 @@ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( return ACTIONS_::kSetText; default: - // TODO might not match to the valid action in arkui + // might not match to the valid action in arkui return ACTIONS_::kCustomAction; } } @@ -1245,7 +1256,8 @@ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( void OhosAccessibilityBridge::DispatchSemanticsAction( int32_t id, flutter::SemanticsAction action, - fml::MallocMapping args) { + fml::MallocMapping args) +{ auto ohos_shell_holder = reinterpret_cast(nativeShellHolder_); ohos_shell_holder->GetPlatformView()->PlatformView::DispatchSemanticsAction( @@ -1262,7 +1274,8 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( int64_t elementId, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments, - int32_t requestId) { + int32_t requestId) +{ FML_DLOG(INFO) << "ExecuteAccessibilityAction input-params-> elementId=" << elementId << " action=" << action << " requestId=" << requestId @@ -1376,7 +1389,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( } else if (flutterNode.HasAction(ACTIONS_::kIncrease)) { flutterNode.value = flutterNode.increasedValue; flutterNode.valueAttributes = flutterNode.increasedValueAttributes; - // TODO: Flutter_SendAccessibilityAsyncEvent() -> selected eventtype + Flutter_SendAccessibilityAsyncEvent( elementId, ArkUI_AccessibilityEventType:: ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); @@ -1416,7 +1429,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( } else if (flutterNode.HasAction(ACTIONS_::kDecrease)) { flutterNode.value = flutterNode.decreasedValue; flutterNode.valueAttributes = flutterNode.decreasedValueAttributes; - // TODO: Flutter_SendAccessibilityAsyncEvent() -> selected eventtype + Flutter_SendAccessibilityAsyncEvent( elementId, ArkUI_AccessibilityEventType:: ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); @@ -1525,24 +1538,13 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; } -int32_t OhosAccessibilityBridge::ClearFocusedFocusAccessibilityNode() { - FML_DLOG(INFO) << "=== ClearFocusedFocusAccessibilityNode is end ==="; - return 0; -} -int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( - int64_t elementId, - int32_t requestId, - int32_t* index) { - FML_DLOG(INFO) << "=== GetAccessibilityNodeCursorPosition is end ==="; - return 0; -} - /** * 自定义无障碍异步事件发送 */ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( int64_t elementId, - ArkUI_AccessibilityEventType eventType) { + ArkUI_AccessibilityEventType eventType) +{ // 1.创建eventInfo对象 ArkUI_AccessibilityEventInfo* eventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); @@ -1598,7 +1600,8 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( * 判断当前语义节点是否获焦 */ bool OhosAccessibilityBridge::IsNodeFocusable( - const flutter::SemanticsNode& node) { + const flutter::SemanticsNode& node) +{ if (node.HasFlag(FLAGS_::kScopesRoute)) { return false; } @@ -1626,20 +1629,19 @@ bool OhosAccessibilityBridge::IsNodeFocusable( void OhosAccessibilityBridge::PerformSetText( flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, - ArkUI_AccessibilityActionArguments* actionArguments) { -} + ArkUI_AccessibilityActionArguments* actionArguments) {} void OhosAccessibilityBridge::PerformSelectText( flutter::SemanticsNode flutterNode, ArkUI_Accessibility_ActionType action, - ArkUI_AccessibilityActionArguments* actionArguments) { -} + ArkUI_AccessibilityActionArguments* actionArguments) {} /** * 获取当前flutter节点的组件类型,并映射为arkui组件 */ std::string OhosAccessibilityBridge::GetNodeComponentType( - const flutter::SemanticsNode& node) { + const flutter::SemanticsNode& node) +{ if (node.HasFlag(FLAGS_::kIsButton)) { return "Button"; } @@ -1693,7 +1695,8 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( } // 获取根节点 -flutter::SemanticsNode OhosAccessibilityBridge::getFlutterRootSemanticsNode() { +flutter::SemanticsNode OhosAccessibilityBridge::getFlutterRootSemanticsNode() +{ if (!flutterSemanticsTree_.size()) { FML_DLOG(ERROR) << "getFlutterRootSemanticsNode -> flutterSemanticsTree_.size()=0"; @@ -1709,7 +1712,8 @@ flutter::SemanticsNode OhosAccessibilityBridge::getFlutterRootSemanticsNode() { void OhosAccessibilityBridge::AddRouteNodes( std::vector edges, - flutter::SemanticsNode node) { + flutter::SemanticsNode node) +{ if (node.HasFlag(FLAGS_::kScopesRoute)) { edges.emplace_back(node); } @@ -1719,7 +1723,8 @@ void OhosAccessibilityBridge::AddRouteNodes( } } -std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) { +std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) +{ if (node.HasFlag(FLAGS_::kNamesRoute) && !node.label.empty()) { return node.label; } @@ -1733,7 +1738,8 @@ std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) { return ""; } -void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { +void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) +{ std::string routeName = GetRouteName(route); if (routeName.empty()) { routeName = " "; @@ -1745,7 +1751,8 @@ void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { } void OhosAccessibilityBridge::removeSemanticsNode( - flutter::SemanticsNode nodeToBeRemoved) { + flutter::SemanticsNode nodeToBeRemoved) +{ if (!flutterSemanticsTree_.size()) { FML_DLOG(ERROR) << "OhosAccessibilityBridge::removeSemanticsNode -> " "flutterSemanticsTree_.szie()=0"; @@ -1770,7 +1777,8 @@ void OhosAccessibilityBridge::removeSemanticsNode( * when the system accessibility service is shut down, * clear all the flutter semantics-relevant caches like maps, vectors */ -void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() { +void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() +{ flutterSemanticsTree_.clear(); parentChildIdVec.clear(); screenRectMap_.clear(); @@ -1779,7 +1787,8 @@ void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() { } void OhosAccessibilityBridge::GetSemanticsNodeDebugInfo( - flutter::SemanticsNode node) { + flutter::SemanticsNode node) +{ FML_DLOG(INFO) << "-------------------SemanticsNode------------------"; SkMatrix _transform = node.transform.asM33(); FML_DLOG(INFO) << "node.id=" << node.id; @@ -1847,7 +1856,8 @@ void OhosAccessibilityBridge::GetSemanticsNodeDebugInfo( } void OhosAccessibilityBridge::GetSemanticsFlagsDebugInfo( - flutter::SemanticsNode node) { + flutter::SemanticsNode node) +{ FML_DLOG(INFO) << "----------------SemanticsFlags-------------------------"; FML_DLOG(INFO) << "kHasCheckedState: " << node.HasFlag(FLAGS_::kHasCheckedState); @@ -1885,7 +1895,8 @@ void OhosAccessibilityBridge::GetSemanticsFlagsDebugInfo( } void OhosAccessibilityBridge::GetCustomActionDebugInfo( - flutter::CustomAccessibilityAction customAccessibilityAction) { + flutter::CustomAccessibilityAction customAccessibilityAction) +{ FML_DLOG(INFO) << "--------------CustomAccessibilityAction------------"; FML_DLOG(INFO) << "customAccessibilityAction.id=" << customAccessibilityAction.id; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index a170e4b789..adff92de57 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -42,7 +42,8 @@ struct AbsoluteRect { float right; float bottom; - static constexpr AbsoluteRect MakeEmpty() { + static constexpr AbsoluteRect MakeEmpty() + { return AbsoluteRect{0.0, 0.0, 0.0, 0.0}; } }; @@ -161,6 +162,22 @@ class OhosAccessibilityBridge { std::unordered_map actions_mp_; std::vector flutterNavigationVec_; + const std::unordered_map ArkUI_ACTION_TYPE_MAP_ = { + {"invalid", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID}, + {"click", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK}, + {"long press", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK}, + {"focus acquisition", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS}, + {"focus clearance", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS}, + {"forward scroll", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD}, + {"backward scroll", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD}, + {"copy text", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY}, + {"paste text", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE}, + {"cut text", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT}, + {"text selection", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT}, + {"set text", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT}, + {"text cursor position setting", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION}, + }; + static const int32_t FOCUSABLE_FLAGS = static_cast(FLAGS_::kHasCheckedState) | static_cast(FLAGS_::kIsChecked) | @@ -185,6 +202,9 @@ class OhosAccessibilityBridge { void FlutterSetElementInfoProperties( ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId); + void FlutterSetElementInfoOperationActions( + ArkUI_AccessibilityElementInfo* elementInfoFromList, + std::string widget_type); void FlutterTreeToArkuiTree( ArkUI_AccessibilityElementInfoList* elementInfoList); @@ -229,6 +249,8 @@ class OhosAccessibilityBridge { void PageStateUpdate(int64_t elementId); void RequestFocusWhenPageUpdate(); + + bool Contains(const std::string& source, const std::string& target); }; } // namespace flutter diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index f77c511b15..18977911e5 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -584,7 +584,6 @@ napi_value PlatformViewOHOSNapi::nativeUpdateOhosAssetManager( napi_callback_info info) { LOGD("PlatformViewOHOSNapi::nativeUpdateOhosAssetManager"); - // TODO: return nullptr; } @@ -595,7 +594,6 @@ napi_value PlatformViewOHOSNapi::nativeGetPixelMap(napi_env env, napi_callback_info info) { LOGD("PlatformViewOHOSNapi::nativeGetPixelMap"); - // TODO: return nullptr; } diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp index 8d032a0b3e..fa3254d0a4 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.cpp +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -271,10 +271,10 @@ void XComponentBase::BindXComponentCallback() { /** Called when need to get element infos based on a specified node. */ int32_t FindAccessibilityNodeInfosById( - int64_t elementId, - ArkUI_AccessibilitySearchMode mode, - int32_t requestId, - ArkUI_AccessibilityElementInfoList* elementList) + int64_t elementId, + ArkUI_AccessibilitySearchMode mode, + int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList) { auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge->FindAccessibilityNodeInfosById(elementId, mode, requestId, elementList); @@ -284,10 +284,10 @@ int32_t FindAccessibilityNodeInfosById( /** Called when need to get element infos based on a specified node and text content. */ int32_t FindAccessibilityNodeInfosByText( - int64_t elementId, - const char* text, - int32_t requestId, - ArkUI_AccessibilityElementInfoList* elementList) + int64_t elementId, + const char* text, + int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList) { auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge->FindAccessibilityNodeInfosByText(elementId, text, requestId, elementList); @@ -297,8 +297,10 @@ int32_t FindAccessibilityNodeInfosByText( /** Called when need to get the focused element info based on a specified node. */ int32_t FindFocusedAccessibilityNode( -int64_t elementId, ArkUI_AccessibilityFocusType focusType, -int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo) + int64_t elementId, + ArkUI_AccessibilityFocusType focusType, + int32_t requestId, + ArkUI_AccessibilityElementInfo* elementinfo) { auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge->FindFocusedAccessibilityNode(elementId, focusType, requestId, elementinfo); @@ -308,10 +310,10 @@ int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo) /** Query the node that can be focused based on the reference node. Query the next node that can be focused based on the mode and direction. */ int32_t FindNextFocusAccessibilityNode( - int64_t elementId, - ArkUI_AccessibilityFocusMoveDirection direction, - int32_t requestId, - ArkUI_AccessibilityElementInfo *elementList) + int64_t elementId, + ArkUI_AccessibilityFocusMoveDirection direction, + int32_t requestId, + ArkUI_AccessibilityElementInfo *elementList) { auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge->FindNextFocusAccessibilityNode(elementId, direction, requestId, elementList); @@ -321,10 +323,10 @@ int32_t FindNextFocusAccessibilityNode( /** Performing the Action operation on a specified node. */ int32_t ExecuteAccessibilityAction( - int64_t elementId, - ArkUI_Accessibility_ActionType action, - ArkUI_AccessibilityActionArguments* actionArguments, - int32_t requestId) + int64_t elementId, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments, + int32_t requestId) { auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge->ExecuteAccessibilityAction(elementId, action, actionArguments, requestId); @@ -341,9 +343,9 @@ int32_t ClearFocusedFocusAccessibilityNode() /** Queries the current cursor position of a specified node. */ int32_t GetAccessibilityNodeCursorPosition( - int64_t elementId, - int32_t requestId, - int32_t* index) + int64_t elementId, + int32_t requestId, + int32_t* index) { auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); ohosAccessibilityBridge->GetAccessibilityNodeCursorPosition(elementId, requestId, index); @@ -405,13 +407,15 @@ void XComponentBase::SetNativeXComponent(OH_NativeXComponent* nativeXComponent){ BindAccessibilityProviderCallback(); ArkUI_AccessibilityProvider* accessibilityProvider = nullptr; - int32_t ret1 = OH_NativeXComponent_GetNativeAccessibilityProvider(nativeXComponent_, &accessibilityProvider); - if(ret1 != 0) { + int32_t ret1 = OH_NativeXComponent_GetNativeAccessibilityProvider( + nativeXComponent_, &accessibilityProvider); + if (ret1 != 0) { LOGE("OH_NativeXComponent_GetNativeAccessibilityProvider is failed"); return; } - int32_t ret2 = OH_ArkUI_AccessibilityProviderRegisterCallback(accessibilityProvider, &accessibilityProviderCallback_); - if(ret2 != 0) { + int32_t ret2 = OH_ArkUI_AccessibilityProviderRegisterCallback( + accessibilityProvider, &accessibilityProviderCallback_); + if (ret2 != 0) { LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is failed"); return; } -- Gitee From 1d39a71141d411c9dcbcd60c788152bc986c9887 Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 18 Oct 2024 15:04:14 +0800 Subject: [PATCH 066/151] =?UTF-8?q?refactor:C++=E4=BB=A3=E7=A0=81=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 254 ++++++++---------- .../accessibility/ohos_accessibility_bridge.h | 51 ++-- 2 files changed, 145 insertions(+), 160 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 9eec196478..a842572f2a 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -29,29 +29,26 @@ OhosAccessibilityBridge OhosAccessibilityBridge::bridgeInstance; OhosAccessibilityBridge::OhosAccessibilityBridge() {}; OhosAccessibilityBridge::~OhosAccessibilityBridge() {}; -OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() -{ +OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() { return &OhosAccessibilityBridge::bridgeInstance; } /** * 当页面状态更新事件,在页面转换、切换、调整大小时发送页面状态更新事件 */ -void OhosAccessibilityBridge::PageStateUpdate(int64_t elementId) -{ +void OhosAccessibilityBridge::PageStateUpdate(int64_t elementId) { ArkUI_AccessibilityEventInfo* pageUpdateEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); ArkUI_AccessibilityElementInfo* _elementInfo = - OH_ArkUI_CreateAccessibilityElementInfo(); + OH_ArkUI_CreateAccessibilityElementInfo(); OH_ArkUI_AccessibilityEventSetEventType( pageUpdateEventInfo, ArkUI_AccessibilityEventType:: ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED); FlutterNodeToElementInfoById(_elementInfo, elementId); - OH_ArkUI_AccessibilityEventSetElementInfo(pageUpdateEventInfo, - _elementInfo); + OH_ArkUI_AccessibilityEventSetElementInfo(pageUpdateEventInfo, _elementInfo); auto callback = [](int32_t errorCode) { FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; @@ -74,8 +71,7 @@ void OhosAccessibilityBridge::PageStateUpdate(int64_t elementId) /** * 特定节点的焦点请求 (当页面更新时自动请求id=0节点获焦) */ -void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() -{ +void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() { ArkUI_AccessibilityEventInfo* reqFocusEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); ArkUI_AccessibilityElementInfo* elementInfo = @@ -112,12 +108,11 @@ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() */ void OhosAccessibilityBridge::updateSemantics( flutter::SemanticsNodeUpdates update, - flutter::CustomAccessibilityActionUpdates actions) -{ + flutter::CustomAccessibilityActionUpdates actions) { FML_DLOG(INFO) << ("OhosAccessibilityBridge::updateSemantics is called"); // 当flutter页面更新时,自动请求id=0节点组件获焦(滑动组件除外) - if(IS_FLUTTER_NAVIGATE) { + if (IS_FLUTTER_NAVIGATE) { RequestFocusWhenPageUpdate(); IS_FLUTTER_NAVIGATE = false; } @@ -173,8 +168,9 @@ void OhosAccessibilityBridge::updateSemantics( // 判断是否触发liveRegion活动区,当前节点是否活跃(暂不影响正常功能) if (node.HasFlag(FLAGS_::kIsLiveRegion)) { - FML_DLOG(INFO) << "UpdateSemantics -> flutterNode is kIsLiveRegion, node.id=" - << node.id; + FML_DLOG(INFO) + << "UpdateSemantics -> flutterNode is kIsLiveRegion, node.id=" + << node.id; } } @@ -203,8 +199,7 @@ void OhosAccessibilityBridge::updateSemantics( */ void OhosAccessibilityBridge::FlutterScrollExecution( flutter::SemanticsNode node, - ArkUI_AccessibilityElementInfo* elementInfoFromList) -{ + ArkUI_AccessibilityElementInfo* elementInfoFromList) { double nodePosition = node.scrollPosition; double nodeScrollExtentMax = node.scrollExtentMax; double nodeScrollExtentMin = node.scrollExtentMin; @@ -277,8 +272,7 @@ void OhosAccessibilityBridge::FlutterScrollExecution( * derived struct SemanticsNodeExtent */ SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent( - flutter::SemanticsNode node) -{ + flutter::SemanticsNode node) { SemanticsNodeExtent nodeEx = SemanticsNodeExtent(); nodeEx.id = std::move(node.id); nodeEx.flags = std::move(node.flags); @@ -322,16 +316,14 @@ SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent( * 判断当前节点是否已经滑动 */ bool OhosAccessibilityBridge::HasScrolled( - const flutter::SemanticsNode& flutterNode) -{ + const flutter::SemanticsNode& flutterNode) { return flutterNode.scrollPosition != std::nan(""); } /** * 判断是否可滑动 */ bool OhosAccessibilityBridge::IsNodeScrollable( - flutter::SemanticsNode flutterNode) -{ + flutter::SemanticsNode flutterNode) { return flutterNode.HasAction(ACTIONS_::kScrollLeft) || flutterNode.HasAction(ACTIONS_::kScrollRight) || flutterNode.HasAction(ACTIONS_::kScrollUp) || @@ -341,16 +333,14 @@ bool OhosAccessibilityBridge::IsNodeScrollable( * 判断当前节点组件是否是滑动组件,如: listview, gridview等 */ bool OhosAccessibilityBridge::IsScrollableWidget( - flutter::SemanticsNode flutterNode) -{ + flutter::SemanticsNode flutterNode) { return flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); } /** * 主动播报特定文本 */ -void OhosAccessibilityBridge::announce(std::unique_ptr& message) -{ +void OhosAccessibilityBridge::announce(std::unique_ptr& message) { // 创建并设置屏幕朗读事件 ArkUI_AccessibilityEventInfo* announceEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); @@ -380,8 +370,7 @@ void OhosAccessibilityBridge::announce(std::unique_ptr& message) * 根据nodeid获取或创建flutter语义节点 */ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode( - int32_t id) -{ + int32_t id) { flutter::SemanticsNode node; if (flutterSemanticsTree_.count(id) > 0) { return flutterSemanticsTree_.at(id); @@ -397,8 +386,7 @@ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode( * flutter的语义节点初始化配置给arkui创建的elementInfos */ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( - ArkUI_AccessibilityElementInfoList* elementInfoList) -{ + ArkUI_AccessibilityElementInfoList* elementInfoList) { if (flutterSemanticsTree_.size() == 0) { FML_DLOG(ERROR) << "OhosAccessibilityBridge::FlutterTreeToArkuiTree " "flutterSemanticsTree_.size() = 0"; @@ -482,8 +470,7 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( /** * 获取当前elementid的父节点id */ -int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) -{ +int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) { int32_t childElementId = static_cast(elementId); if (!parentChildIdVec.size()) { FML_DLOG(INFO) @@ -505,8 +492,7 @@ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, float left, float top, float right, - float bottom) -{ + float bottom) { screenRectMap_[flutterNodeId] = std::make_pair(std::make_pair(left, top), std::make_pair(right, bottom)); FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId @@ -530,8 +516,7 @@ OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) { * 目前暂未考虑旋转、透视场景,不影响屏幕朗读功能 */ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( - flutter::SemanticsNode currNode) -{ + flutter::SemanticsNode currNode) { // 获取当前flutter节点的相对rect auto currLeft = static_cast(currNode.rect.fLeft); auto currTop = static_cast(currNode.rect.fTop); @@ -631,8 +616,7 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( */ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( ArkUI_AccessibilityElementInfo* elementInfoFromList, - int64_t elementId) -{ + int64_t elementId) { if (elementInfoFromList == nullptr) { FML_DLOG(INFO) << "OhosAccessibilityBridge::FlutterNodeToElementInfoById " "elementInfoFromList is null"; @@ -710,9 +694,9 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( /** * 判断源字符串是否包含目标字符串 */ -bool OhosAccessibilityBridge::Contains(const std::string& source, const std::string& target) -{ - return source.find(target) != std::string::npos; +bool OhosAccessibilityBridge::Contains(const std::string& source, + const std::string& target) { + return source.find(target) != std::string::npos; } /** @@ -720,66 +704,79 @@ bool OhosAccessibilityBridge::Contains(const std::string& source, const std::str */ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( ArkUI_AccessibilityElementInfo* elementInfoFromList, - std::string widget_type) -{ - //计算不同组件类型的action类型数组数量 + std::string widget_type) { + // 计算不同组件类型的action类型数组数量 int32_t actionTypeNum = 0; if (widget_type == "textfield") { - for (const auto action_item: ArkUI_ACTION_TYPE_MAP_) { - std::string action_description= action_item.first; - if (Contains(action_description, "focus")) { actionTypeNum++; }; - if (Contains(action_description, "click")) { actionTypeNum++; }; - if (Contains(action_description, "text")) { actionTypeNum++; }; - if (Contains(action_description, "press")) { actionTypeNum++; }; + for (const auto action_item : ArkUI_ACTION_TYPE_MAP_) { + std::string action_description = action_item.first; + if (Contains(action_description, "focus")) { + actionTypeNum++; + }; + if (Contains(action_description, "click")) { + actionTypeNum++; + }; + if (Contains(action_description, "text")) { + actionTypeNum++; + }; + if (Contains(action_description, "press")) { + actionTypeNum++; + }; } } else if (widget_type == "scrollable") { - for (const auto action_item: ArkUI_ACTION_TYPE_MAP_) { - std::string action_description= action_item.first; - if (Contains(action_description, "focus")) { actionTypeNum++; }; - if (Contains(action_description, "click")) { actionTypeNum++; }; - if (Contains(action_description, "scroll")) { actionTypeNum++; }; + for (const auto action_item : ArkUI_ACTION_TYPE_MAP_) { + std::string action_description = action_item.first; + if (Contains(action_description, "focus")) { + actionTypeNum++; + }; + if (Contains(action_description, "click")) { + actionTypeNum++; + }; + if (Contains(action_description, "scroll")) { + actionTypeNum++; + }; } } else { - for (const auto action_item: ArkUI_ACTION_TYPE_MAP_) { - std::string action_description= action_item.first; - if (Contains(action_description, "focus")) { actionTypeNum++; }; - if (Contains(action_description, "click")) { actionTypeNum++; }; + for (const auto action_item : ArkUI_ACTION_TYPE_MAP_) { + std::string action_description = action_item.first; + if (Contains(action_description, "focus")) { + actionTypeNum++; + }; + if (Contains(action_description, "click")) { + actionTypeNum++; + }; } } - //配置相应组件的action操作属性 + // 配置相应组件的action操作属性 ArkUI_AccessibleAction actions[actionTypeNum]; int32_t count = 0; - for (const auto item: ArkUI_ACTION_TYPE_MAP_) { + for (const auto item : ArkUI_ACTION_TYPE_MAP_) { std::string description = item.first; if (widget_type == "textfield") { - //textfield组件类型包含focus, text, click, long press动作类型 - if (Contains(description, "focus") || - Contains(description, "click") || - Contains(description, "text") || - Contains(description, "press")) { + // textfield组件类型包含focus, text, click, long press动作类型 + if (Contains(description, "focus") || Contains(description, "click") || + Contains(description, "text") || Contains(description, "press")) { actions[count++].actionType = item.second; - actions[count-1].description = description.c_str(); + actions[count - 1].description = description.c_str(); } } else if (widget_type == "scrollable") { - //可滑动组件类型包含focus, scroll, click动作类型 - if (Contains(description, "focus") || - Contains(description, "click") || + // 可滑动组件类型包含focus, scroll, click动作类型 + if (Contains(description, "focus") || Contains(description, "click") || Contains(description, "scroll")) { actions[count++].actionType = item.second; - actions[count-1].description = description.c_str(); + actions[count - 1].description = description.c_str(); } } else { - //通用组件包含点击、获焦、失焦 - if (Contains(description, "focus") || - Contains(description, "click")) { + // 通用组件包含点击、获焦、失焦 + if (Contains(description, "focus") || Contains(description, "click")) { actions[count++].actionType = item.second; - actions[count-1].description = description.c_str(); + actions[count - 1].description = description.c_str(); } } } - //set elementinfo OperationActions - OH_ArkUI_AccessibilityElementInfoSetOperationActions( - elementInfoFromList, actionTypeNum, actions); + // set elementinfo OperationActions + OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, + actionTypeNum, actions); } /** @@ -787,8 +784,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( */ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( ArkUI_AccessibilityElementInfo* elementInfoFromList, - int64_t elementId) -{ + int64_t elementId) { flutter::SemanticsNode flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); @@ -809,17 +805,17 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( << flutterNode.id << " SceenRect = (" << left << ", " << top << ", " << right << ", " << bottom << ")"; - //配置arkui的elementinfo可操作动作属性 + // 配置arkui的elementinfo可操作动作属性 if (IsTextField(flutterNode)) { - //若当前flutter节点为文本输入框组件 + // 若当前flutter节点为文本输入框组件 std::string widget_type = "textfield"; FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); } else if (IsScrollableWidget(flutterNode) || IsNodeScrollable(flutterNode)) { - //若当前flutter节点为可滑动组件类型 + // 若当前flutter节点为可滑动组件类型 std::string widget_type = "scrollable"; FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); } else { - //若当前flutter节点为通用组件 + // 若当前flutter节点为通用组件 std::string widget_type = "common"; FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); } @@ -970,23 +966,20 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( /** * 判断当前节点是否为textfield文本框 */ -bool OhosAccessibilityBridge::IsTextField(flutter::SemanticsNode flutterNode) -{ +bool OhosAccessibilityBridge::IsTextField(flutter::SemanticsNode flutterNode) { return flutterNode.HasFlag(FLAGS_::kIsTextField); } /** * 判断当前节点是否为滑动条slider类型 */ -bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) -{ +bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) { return flutterNode.HasFlag(FLAGS_::kIsSlider); } /** * 判断当前flutter节点组件是否可点击 */ bool OhosAccessibilityBridge::IsNodeClickable( - flutter::SemanticsNode flutterNode) -{ + flutter::SemanticsNode flutterNode) { return flutterNode.HasAction(ACTIONS_::kTap) || flutterNode.HasFlag(FLAGS_::kHasCheckedState) || flutterNode.HasFlag(FLAGS_::kIsButton) || @@ -1004,16 +997,14 @@ bool OhosAccessibilityBridge::IsNodeClickable( * 判断当前flutter节点组件是否可显示 */ bool OhosAccessibilityBridge::IsNodeVisible( - flutter::SemanticsNode flutterNode) -{ + flutter::SemanticsNode flutterNode) { return flutterNode.HasFlag(FLAGS_::kIsHidden) ? false : true; } /** * 判断当前flutter节点组件是否具备checkable属性 */ bool OhosAccessibilityBridge::IsNodeCheckable( - flutter::SemanticsNode flutterNode) -{ + flutter::SemanticsNode flutterNode) { return flutterNode.HasFlag(FLAGS_::kHasCheckedState) || flutterNode.HasFlag(FLAGS_::kHasToggledState); } @@ -1021,8 +1012,7 @@ bool OhosAccessibilityBridge::IsNodeCheckable( * 判断当前flutter节点组件是否checked/unchecked(checkbox、radio button) */ bool OhosAccessibilityBridge::IsNodeChecked( - flutter::SemanticsNode flutterNode) -{ + flutter::SemanticsNode flutterNode) { return flutterNode.HasFlag(FLAGS_::kIsChecked) || flutterNode.HasFlag(FLAGS_::kIsToggled); } @@ -1030,8 +1020,7 @@ bool OhosAccessibilityBridge::IsNodeChecked( * 判断当前flutter节点组件是否选中 */ bool OhosAccessibilityBridge::IsNodeSelected( - flutter::SemanticsNode flutterNode) -{ + flutter::SemanticsNode flutterNode) { return flutterNode.HasFlag(FLAGS_::kIsSelected); } /** @@ -1046,16 +1035,14 @@ bool OhosAccessibilityBridge::IsNodePassword( * 判断当前flutter节点组件是否支持长按功能 */ bool OhosAccessibilityBridge::IsNodeHasLongPress( - flutter::SemanticsNode flutterNode) -{ + flutter::SemanticsNode flutterNode) { return flutterNode.HasAction(ACTIONS_::kLongPress); } /** * 判断当前flutter节点是否enabled */ bool OhosAccessibilityBridge::IsNodeEnabled( - flutter::SemanticsNode flutterNode) -{ + flutter::SemanticsNode flutterNode) { return !flutterNode.HasFlag(FLAGS_::kHasEnabledState) || flutterNode.HasFlag(FLAGS_::kIsEnabled); } @@ -1068,8 +1055,7 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( int64_t elementId, ArkUI_AccessibilitySearchMode mode, int32_t requestId, - ArkUI_AccessibilityElementInfoList* elementList) -{ + ArkUI_AccessibilityElementInfoList* elementList) { FML_DLOG(INFO) << "#### FindAccessibilityNodeInfosById input-params ####: elementId = " << elementId << " mode=" << mode << " requestId=" << requestId @@ -1154,8 +1140,7 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosByText( int64_t elementId, const char* text, int32_t requestId, - ArkUI_AccessibilityElementInfoList* elementList) -{ + ArkUI_AccessibilityElementInfoList* elementList) { FML_DLOG(INFO) << "=== FindAccessibilityNodeInfosByText is end ==="; return 0; } @@ -1163,8 +1148,7 @@ int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( int64_t elementId, ArkUI_AccessibilityFocusType focusType, int32_t requestId, - ArkUI_AccessibilityElementInfo* elementinfo) -{ + ArkUI_AccessibilityElementInfo* elementinfo) { FML_DLOG(INFO) << "=== FindFocusedAccessibilityNode is end ==="; return 0; @@ -1173,22 +1157,19 @@ int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( int64_t elementId, ArkUI_AccessibilityFocusMoveDirection direction, int32_t requestId, - ArkUI_AccessibilityElementInfo* elementList) -{ + ArkUI_AccessibilityElementInfo* elementList) { FML_DLOG(INFO) << "=== FindNextFocusAccessibilityNode is end ==="; return 0; } -int32_t OhosAccessibilityBridge::ClearFocusedFocusAccessibilityNode() -{ +int32_t OhosAccessibilityBridge::ClearFocusedFocusAccessibilityNode() { FML_DLOG(INFO) << "=== ClearFocusedFocusAccessibilityNode is end ==="; return 0; } int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( int64_t elementId, int32_t requestId, - int32_t* index) -{ + int32_t* index) { FML_DLOG(INFO) << "=== GetAccessibilityNodeCursorPosition is end ==="; return 0; } @@ -1197,8 +1178,7 @@ int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( * 将arkui的action类型转化为flutter的action类型 */ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( - ArkUI_Accessibility_ActionType arkui_action) -{ + ArkUI_Accessibility_ActionType arkui_action) { switch (arkui_action) { case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: @@ -1256,8 +1236,7 @@ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( void OhosAccessibilityBridge::DispatchSemanticsAction( int32_t id, flutter::SemanticsAction action, - fml::MallocMapping args) -{ + fml::MallocMapping args) { auto ohos_shell_holder = reinterpret_cast(nativeShellHolder_); ohos_shell_holder->GetPlatformView()->PlatformView::DispatchSemanticsAction( @@ -1274,8 +1253,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( int64_t elementId, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments, - int32_t requestId) -{ + int32_t requestId) { FML_DLOG(INFO) << "ExecuteAccessibilityAction input-params-> elementId=" << elementId << " action=" << action << " requestId=" << requestId @@ -1543,8 +1521,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( */ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( int64_t elementId, - ArkUI_AccessibilityEventType eventType) -{ + ArkUI_AccessibilityEventType eventType) { // 1.创建eventInfo对象 ArkUI_AccessibilityEventInfo* eventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); @@ -1600,8 +1577,7 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( * 判断当前语义节点是否获焦 */ bool OhosAccessibilityBridge::IsNodeFocusable( - const flutter::SemanticsNode& node) -{ + const flutter::SemanticsNode& node) { if (node.HasFlag(FLAGS_::kScopesRoute)) { return false; } @@ -1640,8 +1616,7 @@ void OhosAccessibilityBridge::PerformSelectText( * 获取当前flutter节点的组件类型,并映射为arkui组件 */ std::string OhosAccessibilityBridge::GetNodeComponentType( - const flutter::SemanticsNode& node) -{ + const flutter::SemanticsNode& node) { if (node.HasFlag(FLAGS_::kIsButton)) { return "Button"; } @@ -1695,8 +1670,7 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( } // 获取根节点 -flutter::SemanticsNode OhosAccessibilityBridge::getFlutterRootSemanticsNode() -{ +flutter::SemanticsNode OhosAccessibilityBridge::getFlutterRootSemanticsNode() { if (!flutterSemanticsTree_.size()) { FML_DLOG(ERROR) << "getFlutterRootSemanticsNode -> flutterSemanticsTree_.size()=0"; @@ -1712,8 +1686,7 @@ flutter::SemanticsNode OhosAccessibilityBridge::getFlutterRootSemanticsNode() void OhosAccessibilityBridge::AddRouteNodes( std::vector edges, - flutter::SemanticsNode node) -{ + flutter::SemanticsNode node) { if (node.HasFlag(FLAGS_::kScopesRoute)) { edges.emplace_back(node); } @@ -1723,8 +1696,7 @@ void OhosAccessibilityBridge::AddRouteNodes( } } -std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) -{ +std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) { if (node.HasFlag(FLAGS_::kNamesRoute) && !node.label.empty()) { return node.label; } @@ -1738,8 +1710,7 @@ std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) return ""; } -void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) -{ +void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { std::string routeName = GetRouteName(route); if (routeName.empty()) { routeName = " "; @@ -1751,8 +1722,7 @@ void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) } void OhosAccessibilityBridge::removeSemanticsNode( - flutter::SemanticsNode nodeToBeRemoved) -{ + flutter::SemanticsNode nodeToBeRemoved) { if (!flutterSemanticsTree_.size()) { FML_DLOG(ERROR) << "OhosAccessibilityBridge::removeSemanticsNode -> " "flutterSemanticsTree_.szie()=0"; @@ -1777,8 +1747,7 @@ void OhosAccessibilityBridge::removeSemanticsNode( * when the system accessibility service is shut down, * clear all the flutter semantics-relevant caches like maps, vectors */ -void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() -{ +void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() { flutterSemanticsTree_.clear(); parentChildIdVec.clear(); screenRectMap_.clear(); @@ -1787,8 +1756,7 @@ void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() } void OhosAccessibilityBridge::GetSemanticsNodeDebugInfo( - flutter::SemanticsNode node) -{ + flutter::SemanticsNode node) { FML_DLOG(INFO) << "-------------------SemanticsNode------------------"; SkMatrix _transform = node.transform.asM33(); FML_DLOG(INFO) << "node.id=" << node.id; @@ -1856,8 +1824,7 @@ void OhosAccessibilityBridge::GetSemanticsNodeDebugInfo( } void OhosAccessibilityBridge::GetSemanticsFlagsDebugInfo( - flutter::SemanticsNode node) -{ + flutter::SemanticsNode node) { FML_DLOG(INFO) << "----------------SemanticsFlags-------------------------"; FML_DLOG(INFO) << "kHasCheckedState: " << node.HasFlag(FLAGS_::kHasCheckedState); @@ -1895,8 +1862,7 @@ void OhosAccessibilityBridge::GetSemanticsFlagsDebugInfo( } void OhosAccessibilityBridge::GetCustomActionDebugInfo( - flutter::CustomAccessibilityAction customAccessibilityAction) -{ + flutter::CustomAccessibilityAction customAccessibilityAction) { FML_DLOG(INFO) << "--------------CustomAccessibilityAction------------"; FML_DLOG(INFO) << "customAccessibilityAction.id=" << customAccessibilityAction.id; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index adff92de57..846624da72 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -42,8 +42,7 @@ struct AbsoluteRect { float right; float bottom; - static constexpr AbsoluteRect MakeEmpty() - { + static constexpr AbsoluteRect MakeEmpty() { return AbsoluteRect{0.0, 0.0, 0.0, 0.0}; } }; @@ -162,20 +161,40 @@ class OhosAccessibilityBridge { std::unordered_map actions_mp_; std::vector flutterNavigationVec_; - const std::unordered_map ArkUI_ACTION_TYPE_MAP_ = { - {"invalid", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID}, - {"click", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK}, - {"long press", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK}, - {"focus acquisition", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS}, - {"focus clearance", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS}, - {"forward scroll", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD}, - {"backward scroll", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD}, - {"copy text", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY}, - {"paste text", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE}, - {"cut text", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT}, - {"text selection", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT}, - {"set text", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT}, - {"text cursor position setting", ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION}, + const std::unordered_map + ArkUI_ACTION_TYPE_MAP_ = { + {"invalid", ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID}, + {"click", ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK}, + {"long press", ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK}, + {"focus acquisition", + ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS}, + {"focus clearance", + ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS}, + {"forward scroll", + ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD}, + {"backward scroll", + ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD}, + {"copy text", ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY}, + {"paste text", ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE}, + {"cut text", ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT}, + {"text selection", + ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT}, + {"set text", ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT}, + {"text cursor position setting", + ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION}, }; static const int32_t FOCUSABLE_FLAGS = -- Gitee From 22884163426a91c2c198f07f9db2b61cd9c6d658 Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 18 Oct 2024 15:26:22 +0800 Subject: [PATCH 067/151] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E4=B8=BB?= =?UTF-8?q?=E5=8A=A8=E6=9C=97=E8=AF=BB=E8=87=AA=E5=AE=9A=E4=B9=89=E6=96=87?= =?UTF-8?q?=E5=AD=97bug=EF=BC=8C=E4=BB=A3=E7=A0=81=E5=B7=A6=E6=8B=AC?= =?UTF-8?q?=E5=8F=B7=E6=8D=A2=E8=A1=8C=E6=A0=BC=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 164 ++++++++++++------ 1 file changed, 114 insertions(+), 50 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index a842572f2a..ce94f3902c 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -29,14 +29,16 @@ OhosAccessibilityBridge OhosAccessibilityBridge::bridgeInstance; OhosAccessibilityBridge::OhosAccessibilityBridge() {}; OhosAccessibilityBridge::~OhosAccessibilityBridge() {}; -OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() { +OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() +{ return &OhosAccessibilityBridge::bridgeInstance; } /** * 当页面状态更新事件,在页面转换、切换、调整大小时发送页面状态更新事件 */ -void OhosAccessibilityBridge::PageStateUpdate(int64_t elementId) { +void OhosAccessibilityBridge::PageStateUpdate(int64_t elementId) +{ ArkUI_AccessibilityEventInfo* pageUpdateEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); @@ -71,7 +73,8 @@ void OhosAccessibilityBridge::PageStateUpdate(int64_t elementId) { /** * 特定节点的焦点请求 (当页面更新时自动请求id=0节点获焦) */ -void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() { +void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() +{ ArkUI_AccessibilityEventInfo* reqFocusEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); ArkUI_AccessibilityElementInfo* elementInfo = @@ -108,7 +111,8 @@ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() { */ void OhosAccessibilityBridge::updateSemantics( flutter::SemanticsNodeUpdates update, - flutter::CustomAccessibilityActionUpdates actions) { + flutter::CustomAccessibilityActionUpdates actions) +{ FML_DLOG(INFO) << ("OhosAccessibilityBridge::updateSemantics is called"); // 当flutter页面更新时,自动请求id=0节点组件获焦(滑动组件除外) @@ -199,7 +203,8 @@ void OhosAccessibilityBridge::updateSemantics( */ void OhosAccessibilityBridge::FlutterScrollExecution( flutter::SemanticsNode node, - ArkUI_AccessibilityElementInfo* elementInfoFromList) { + ArkUI_AccessibilityElementInfo* elementInfoFromList) +{ double nodePosition = node.scrollPosition; double nodeScrollExtentMax = node.scrollExtentMax; double nodeScrollExtentMin = node.scrollExtentMin; @@ -272,7 +277,8 @@ void OhosAccessibilityBridge::FlutterScrollExecution( * derived struct SemanticsNodeExtent */ SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent( - flutter::SemanticsNode node) { + flutter::SemanticsNode node) +{ SemanticsNodeExtent nodeEx = SemanticsNodeExtent(); nodeEx.id = std::move(node.id); nodeEx.flags = std::move(node.flags); @@ -316,14 +322,16 @@ SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent( * 判断当前节点是否已经滑动 */ bool OhosAccessibilityBridge::HasScrolled( - const flutter::SemanticsNode& flutterNode) { + const flutter::SemanticsNode& flutterNode) +{ return flutterNode.scrollPosition != std::nan(""); } /** * 判断是否可滑动 */ bool OhosAccessibilityBridge::IsNodeScrollable( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasAction(ACTIONS_::kScrollLeft) || flutterNode.HasAction(ACTIONS_::kScrollRight) || flutterNode.HasAction(ACTIONS_::kScrollUp) || @@ -333,14 +341,16 @@ bool OhosAccessibilityBridge::IsNodeScrollable( * 判断当前节点组件是否是滑动组件,如: listview, gridview等 */ bool OhosAccessibilityBridge::IsScrollableWidget( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); } /** * 主动播报特定文本 */ -void OhosAccessibilityBridge::announce(std::unique_ptr& message) { +void OhosAccessibilityBridge::announce(std::unique_ptr& message) +{ // 创建并设置屏幕朗读事件 ArkUI_AccessibilityEventInfo* announceEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); @@ -363,6 +373,20 @@ void OhosAccessibilityBridge::announce(std::unique_ptr& message) { } FML_DLOG(INFO) << ("OhosAccessibilityBridge::announce message: ") << (message.get()); + + auto callback = [](int32_t errorCode) { + FML_DLOG(WARNING) << "announce callback-> errorCode =" << errorCode; + }; + + if (provider_ == nullptr) { + FML_DLOG(ERROR) << "announce ->" + "AccessibilityProvider = nullptr"; + return; + } + OH_ArkUI_SendAccessibilityAsyncEvent(provider_, announceEventInfo, callback); + + OH_ArkUI_DestoryAccessibilityEventInfo(announceEventInfo); + return; } @@ -370,7 +394,8 @@ void OhosAccessibilityBridge::announce(std::unique_ptr& message) { * 根据nodeid获取或创建flutter语义节点 */ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode( - int32_t id) { + int32_t id) +{ flutter::SemanticsNode node; if (flutterSemanticsTree_.count(id) > 0) { return flutterSemanticsTree_.at(id); @@ -386,7 +411,8 @@ flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode( * flutter的语义节点初始化配置给arkui创建的elementInfos */ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( - ArkUI_AccessibilityElementInfoList* elementInfoList) { + ArkUI_AccessibilityElementInfoList* elementInfoList) +{ if (flutterSemanticsTree_.size() == 0) { FML_DLOG(ERROR) << "OhosAccessibilityBridge::FlutterTreeToArkuiTree " "flutterSemanticsTree_.size() = 0"; @@ -470,7 +496,8 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( /** * 获取当前elementid的父节点id */ -int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) { +int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) +{ int32_t childElementId = static_cast(elementId); if (!parentChildIdVec.size()) { FML_DLOG(INFO) @@ -492,7 +519,8 @@ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, float left, float top, float right, - float bottom) { + float bottom) +{ screenRectMap_[flutterNodeId] = std::make_pair(std::make_pair(left, top), std::make_pair(right, bottom)); FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId @@ -501,7 +529,8 @@ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, } std::pair, std::pair> -OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) { +OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) +{ if (!screenRectMap_.empty() && screenRectMap_.count(flutterNodeId) > 0) { return screenRectMap_.at(flutterNodeId); } else { @@ -516,7 +545,8 @@ OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) { * 目前暂未考虑旋转、透视场景,不影响屏幕朗读功能 */ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( - flutter::SemanticsNode currNode) { + flutter::SemanticsNode currNode) +{ // 获取当前flutter节点的相对rect auto currLeft = static_cast(currNode.rect.fLeft); auto currTop = static_cast(currNode.rect.fTop); @@ -616,7 +646,8 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( */ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( ArkUI_AccessibilityElementInfo* elementInfoFromList, - int64_t elementId) { + int64_t elementId) +{ if (elementInfoFromList == nullptr) { FML_DLOG(INFO) << "OhosAccessibilityBridge::FlutterNodeToElementInfoById " "elementInfoFromList is null"; @@ -695,7 +726,8 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( * 判断源字符串是否包含目标字符串 */ bool OhosAccessibilityBridge::Contains(const std::string& source, - const std::string& target) { + const std::string& target) +{ return source.find(target) != std::string::npos; } @@ -704,7 +736,8 @@ bool OhosAccessibilityBridge::Contains(const std::string& source, */ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( ArkUI_AccessibilityElementInfo* elementInfoFromList, - std::string widget_type) { + std::string widget_type) +{ // 计算不同组件类型的action类型数组数量 int32_t actionTypeNum = 0; if (widget_type == "textfield") { @@ -784,7 +817,8 @@ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( */ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( ArkUI_AccessibilityElementInfo* elementInfoFromList, - int64_t elementId) { + int64_t elementId) +{ flutter::SemanticsNode flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); @@ -966,20 +1000,23 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( /** * 判断当前节点是否为textfield文本框 */ -bool OhosAccessibilityBridge::IsTextField(flutter::SemanticsNode flutterNode) { +bool OhosAccessibilityBridge::IsTextField(flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kIsTextField); } /** * 判断当前节点是否为滑动条slider类型 */ -bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) { +bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kIsSlider); } /** * 判断当前flutter节点组件是否可点击 */ bool OhosAccessibilityBridge::IsNodeClickable( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasAction(ACTIONS_::kTap) || flutterNode.HasFlag(FLAGS_::kHasCheckedState) || flutterNode.HasFlag(FLAGS_::kIsButton) || @@ -997,14 +1034,16 @@ bool OhosAccessibilityBridge::IsNodeClickable( * 判断当前flutter节点组件是否可显示 */ bool OhosAccessibilityBridge::IsNodeVisible( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kIsHidden) ? false : true; } /** * 判断当前flutter节点组件是否具备checkable属性 */ bool OhosAccessibilityBridge::IsNodeCheckable( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kHasCheckedState) || flutterNode.HasFlag(FLAGS_::kHasToggledState); } @@ -1012,7 +1051,8 @@ bool OhosAccessibilityBridge::IsNodeCheckable( * 判断当前flutter节点组件是否checked/unchecked(checkbox、radio button) */ bool OhosAccessibilityBridge::IsNodeChecked( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kIsChecked) || flutterNode.HasFlag(FLAGS_::kIsToggled); } @@ -1020,14 +1060,16 @@ bool OhosAccessibilityBridge::IsNodeChecked( * 判断当前flutter节点组件是否选中 */ bool OhosAccessibilityBridge::IsNodeSelected( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kIsSelected); } /** * 判断当前flutter节点组件是否为密码输入框 */ bool OhosAccessibilityBridge::IsNodePassword( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasFlag(FLAGS_::kIsTextField) && flutterNode.HasFlag(FLAGS_::kIsObscured); } @@ -1035,14 +1077,16 @@ bool OhosAccessibilityBridge::IsNodePassword( * 判断当前flutter节点组件是否支持长按功能 */ bool OhosAccessibilityBridge::IsNodeHasLongPress( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return flutterNode.HasAction(ACTIONS_::kLongPress); } /** * 判断当前flutter节点是否enabled */ bool OhosAccessibilityBridge::IsNodeEnabled( - flutter::SemanticsNode flutterNode) { + flutter::SemanticsNode flutterNode) +{ return !flutterNode.HasFlag(FLAGS_::kHasEnabledState) || flutterNode.HasFlag(FLAGS_::kIsEnabled); } @@ -1055,7 +1099,8 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( int64_t elementId, ArkUI_AccessibilitySearchMode mode, int32_t requestId, - ArkUI_AccessibilityElementInfoList* elementList) { + ArkUI_AccessibilityElementInfoList* elementList) +{ FML_DLOG(INFO) << "#### FindAccessibilityNodeInfosById input-params ####: elementId = " << elementId << " mode=" << mode << " requestId=" << requestId @@ -1140,7 +1185,8 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosByText( int64_t elementId, const char* text, int32_t requestId, - ArkUI_AccessibilityElementInfoList* elementList) { + ArkUI_AccessibilityElementInfoList* elementList) +{ FML_DLOG(INFO) << "=== FindAccessibilityNodeInfosByText is end ==="; return 0; } @@ -1148,7 +1194,8 @@ int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( int64_t elementId, ArkUI_AccessibilityFocusType focusType, int32_t requestId, - ArkUI_AccessibilityElementInfo* elementinfo) { + ArkUI_AccessibilityElementInfo* elementinfo) +{ FML_DLOG(INFO) << "=== FindFocusedAccessibilityNode is end ==="; return 0; @@ -1162,14 +1209,16 @@ int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( return 0; } -int32_t OhosAccessibilityBridge::ClearFocusedFocusAccessibilityNode() { +int32_t OhosAccessibilityBridge::ClearFocusedFocusAccessibilityNode() +{ FML_DLOG(INFO) << "=== ClearFocusedFocusAccessibilityNode is end ==="; return 0; } int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( int64_t elementId, int32_t requestId, - int32_t* index) { + int32_t* index) +{ FML_DLOG(INFO) << "=== GetAccessibilityNodeCursorPosition is end ==="; return 0; } @@ -1178,7 +1227,8 @@ int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( * 将arkui的action类型转化为flutter的action类型 */ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( - ArkUI_Accessibility_ActionType arkui_action) { + ArkUI_Accessibility_ActionType arkui_action) +{ switch (arkui_action) { case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: @@ -1236,7 +1286,8 @@ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( void OhosAccessibilityBridge::DispatchSemanticsAction( int32_t id, flutter::SemanticsAction action, - fml::MallocMapping args) { + fml::MallocMapping args) +{ auto ohos_shell_holder = reinterpret_cast(nativeShellHolder_); ohos_shell_holder->GetPlatformView()->PlatformView::DispatchSemanticsAction( @@ -1253,7 +1304,8 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( int64_t elementId, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments, - int32_t requestId) { + int32_t requestId) +{ FML_DLOG(INFO) << "ExecuteAccessibilityAction input-params-> elementId=" << elementId << " action=" << action << " requestId=" << requestId @@ -1521,7 +1573,8 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( */ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( int64_t elementId, - ArkUI_AccessibilityEventType eventType) { + ArkUI_AccessibilityEventType eventType) +{ // 1.创建eventInfo对象 ArkUI_AccessibilityEventInfo* eventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); @@ -1577,7 +1630,8 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( * 判断当前语义节点是否获焦 */ bool OhosAccessibilityBridge::IsNodeFocusable( - const flutter::SemanticsNode& node) { + const flutter::SemanticsNode& node) +{ if (node.HasFlag(FLAGS_::kScopesRoute)) { return false; } @@ -1616,7 +1670,8 @@ void OhosAccessibilityBridge::PerformSelectText( * 获取当前flutter节点的组件类型,并映射为arkui组件 */ std::string OhosAccessibilityBridge::GetNodeComponentType( - const flutter::SemanticsNode& node) { + const flutter::SemanticsNode& node) +{ if (node.HasFlag(FLAGS_::kIsButton)) { return "Button"; } @@ -1670,7 +1725,8 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( } // 获取根节点 -flutter::SemanticsNode OhosAccessibilityBridge::getFlutterRootSemanticsNode() { +flutter::SemanticsNode OhosAccessibilityBridge::getFlutterRootSemanticsNode() +{ if (!flutterSemanticsTree_.size()) { FML_DLOG(ERROR) << "getFlutterRootSemanticsNode -> flutterSemanticsTree_.size()=0"; @@ -1686,7 +1742,8 @@ flutter::SemanticsNode OhosAccessibilityBridge::getFlutterRootSemanticsNode() { void OhosAccessibilityBridge::AddRouteNodes( std::vector edges, - flutter::SemanticsNode node) { + flutter::SemanticsNode node) +{ if (node.HasFlag(FLAGS_::kScopesRoute)) { edges.emplace_back(node); } @@ -1696,7 +1753,8 @@ void OhosAccessibilityBridge::AddRouteNodes( } } -std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) { +std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) +{ if (node.HasFlag(FLAGS_::kNamesRoute) && !node.label.empty()) { return node.label; } @@ -1710,7 +1768,8 @@ std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) { return ""; } -void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { +void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) +{ std::string routeName = GetRouteName(route); if (routeName.empty()) { routeName = " "; @@ -1722,7 +1781,8 @@ void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { } void OhosAccessibilityBridge::removeSemanticsNode( - flutter::SemanticsNode nodeToBeRemoved) { + flutter::SemanticsNode nodeToBeRemoved) +{ if (!flutterSemanticsTree_.size()) { FML_DLOG(ERROR) << "OhosAccessibilityBridge::removeSemanticsNode -> " "flutterSemanticsTree_.szie()=0"; @@ -1747,7 +1807,8 @@ void OhosAccessibilityBridge::removeSemanticsNode( * when the system accessibility service is shut down, * clear all the flutter semantics-relevant caches like maps, vectors */ -void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() { +void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() +{ flutterSemanticsTree_.clear(); parentChildIdVec.clear(); screenRectMap_.clear(); @@ -1756,7 +1817,8 @@ void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() { } void OhosAccessibilityBridge::GetSemanticsNodeDebugInfo( - flutter::SemanticsNode node) { + flutter::SemanticsNode node) +{ FML_DLOG(INFO) << "-------------------SemanticsNode------------------"; SkMatrix _transform = node.transform.asM33(); FML_DLOG(INFO) << "node.id=" << node.id; @@ -1824,7 +1886,8 @@ void OhosAccessibilityBridge::GetSemanticsNodeDebugInfo( } void OhosAccessibilityBridge::GetSemanticsFlagsDebugInfo( - flutter::SemanticsNode node) { + flutter::SemanticsNode node) +{ FML_DLOG(INFO) << "----------------SemanticsFlags-------------------------"; FML_DLOG(INFO) << "kHasCheckedState: " << node.HasFlag(FLAGS_::kHasCheckedState); @@ -1862,7 +1925,8 @@ void OhosAccessibilityBridge::GetSemanticsFlagsDebugInfo( } void OhosAccessibilityBridge::GetCustomActionDebugInfo( - flutter::CustomAccessibilityAction customAccessibilityAction) { + flutter::CustomAccessibilityAction customAccessibilityAction) +{ FML_DLOG(INFO) << "--------------CustomAccessibilityAction------------"; FML_DLOG(INFO) << "customAccessibilityAction.id=" << customAccessibilityAction.id; -- Gitee From 7aad07f67dfebbd48c46cd91acbb81d9c189c769 Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 18 Oct 2024 20:47:03 +0800 Subject: [PATCH 068/151] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E9=87=8D=E6=9E=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 166 ++++++++++-------- .../accessibility/ohos_accessibility_bridge.h | 4 +- 2 files changed, 97 insertions(+), 73 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index ce94f3902c..7a8b081d9c 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -85,7 +85,7 @@ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() ArkUI_AccessibilityEventType:: ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_REQUEST_ACCESSIBILITY_FOCUS); - int32_t requestFocusId = 4; + int32_t requestFocusId = 0; OH_ArkUI_AccessibilityEventSetRequestFocusId(reqFocusEventInfo, requestFocusId); @@ -725,8 +725,8 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( /** * 判断源字符串是否包含目标字符串 */ -bool OhosAccessibilityBridge::Contains(const std::string& source, - const std::string& target) +bool OhosAccessibilityBridge::Contains(const std::string source, + const std::string target) { return source.find(target) != std::string::npos; } @@ -738,78 +738,102 @@ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( ArkUI_AccessibilityElementInfo* elementInfoFromList, std::string widget_type) { - // 计算不同组件类型的action类型数组数量 - int32_t actionTypeNum = 0; if (widget_type == "textfield") { - for (const auto action_item : ArkUI_ACTION_TYPE_MAP_) { - std::string action_description = action_item.first; - if (Contains(action_description, "focus")) { - actionTypeNum++; - }; - if (Contains(action_description, "click")) { - actionTypeNum++; - }; - if (Contains(action_description, "text")) { - actionTypeNum++; - }; - if (Contains(action_description, "press")) { - actionTypeNum++; - }; - } + // set elementinfo action types + int32_t actionTypeNum = 10; + ArkUI_AccessibleAction actions[actionTypeNum]; + + actions[0].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; + actions[0].description = "获取焦点"; + + actions[1].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].description = "清除焦点"; + + actions[2].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; + actions[2].description = "点击操作"; + + actions[3].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK; + actions[3].description = "长按操作"; + + actions[4].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY; + actions[4].description = "文本复制"; + + actions[5].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE; + actions[5].description = "文本粘贴"; + + actions[6].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT; + actions[6].description = "文本剪切"; + + actions[7].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT; + actions[7].description = "文本选择"; + + actions[8].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT; + actions[8].description = "文本内容设置"; + + actions[9].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION; + actions[9].description = "光标位置设置"; + + OH_ArkUI_AccessibilityElementInfoSetOperationActions( + elementInfoFromList, actionTypeNum, actions); + } else if (widget_type == "scrollable") { - for (const auto action_item : ArkUI_ACTION_TYPE_MAP_) { - std::string action_description = action_item.first; - if (Contains(action_description, "focus")) { - actionTypeNum++; - }; - if (Contains(action_description, "click")) { - actionTypeNum++; - }; - if (Contains(action_description, "scroll")) { - actionTypeNum++; - }; - } + // if node is a scrollable component + int32_t actionTypeNum = 5; + ArkUI_AccessibleAction actions[actionTypeNum]; + + actions[0].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; + actions[0].description = "获取焦点"; + + actions[1].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].description = "清除焦点"; + + actions[2].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; + actions[2].description = "点击动作"; + + actions[3].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD; + actions[3].description = "向上滑动"; + + actions[4].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD; + actions[4].description = "向下滑动"; + + OH_ArkUI_AccessibilityElementInfoSetOperationActions( + elementInfoFromList, actionTypeNum, actions); + } else { - for (const auto action_item : ArkUI_ACTION_TYPE_MAP_) { - std::string action_description = action_item.first; - if (Contains(action_description, "focus")) { - actionTypeNum++; - }; - if (Contains(action_description, "click")) { - actionTypeNum++; - }; - } - } - // 配置相应组件的action操作属性 - ArkUI_AccessibleAction actions[actionTypeNum]; - int32_t count = 0; - for (const auto item : ArkUI_ACTION_TYPE_MAP_) { - std::string description = item.first; - if (widget_type == "textfield") { - // textfield组件类型包含focus, text, click, long press动作类型 - if (Contains(description, "focus") || Contains(description, "click") || - Contains(description, "text") || Contains(description, "press")) { - actions[count++].actionType = item.second; - actions[count - 1].description = description.c_str(); - } - } else if (widget_type == "scrollable") { - // 可滑动组件类型包含focus, scroll, click动作类型 - if (Contains(description, "focus") || Contains(description, "click") || - Contains(description, "scroll")) { - actions[count++].actionType = item.second; - actions[count - 1].description = description.c_str(); - } - } else { - // 通用组件包含点击、获焦、失焦 - if (Contains(description, "focus") || Contains(description, "click")) { - actions[count++].actionType = item.second; - actions[count - 1].description = description.c_str(); - } - } + // set common component action types + int32_t actionTypeNum = 3; + ArkUI_AccessibleAction actions[actionTypeNum]; + + actions[0].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; + actions[0].description = "获取焦点"; + + actions[1].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].description = "清除焦点"; + + actions[2].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; + actions[2].description = "点击动作"; + + OH_ArkUI_AccessibilityElementInfoSetOperationActions( + elementInfoFromList, actionTypeNum, actions); } - // set elementinfo OperationActions - OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, - actionTypeNum, actions); } /** diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 846624da72..602df9370b 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -161,7 +161,7 @@ class OhosAccessibilityBridge { std::unordered_map actions_mp_; std::vector flutterNavigationVec_; - const std::unordered_map + const std::map ArkUI_ACTION_TYPE_MAP_ = { {"invalid", ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID}, @@ -269,7 +269,7 @@ class OhosAccessibilityBridge { void PageStateUpdate(int64_t elementId); void RequestFocusWhenPageUpdate(); - bool Contains(const std::string& source, const std::string& target); + bool Contains(const std::string source, const std::string target); }; } // namespace flutter -- Gitee From fa4d15c751277bd197548e111fe23f944e88c878 Mon Sep 17 00:00:00 2001 From: cjand <1747143535@qq.com> Date: Tue, 22 Oct 2024 14:34:25 +0800 Subject: [PATCH 069/151] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=96=E6=8E=A5?= =?UTF-8?q?=E9=94=AE=E7=9B=98=E8=8E=B7=E5=8F=96=E7=84=A6=E7=82=B9=E5=90=8E?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E8=BE=93=E5=85=A5=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: cjand <1747143535@qq.com> --- .../systemchannels/TextInputChannel.ets | 2 ++ .../ets/embedding/ohos/FlutterAbility.ets | 1 + .../main/ets/embedding/ohos/FlutterEntry.ets | 1 + .../ets/plugin/editing/TextInputPlugin.ets | 29 +++++++++++++++++++ 4 files changed, 33 insertions(+) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets index df71b3fb15..eb6eb64f59 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets @@ -182,6 +182,8 @@ export interface TextInputMethodHandler { clearClient(): void; + handleChangeFocus(focusState: boolean): void; + } export class Configuration { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets index 4013fed189..edfb59ca4c 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets @@ -151,6 +151,7 @@ export class FlutterAbility extends UIAbility implements Host { case window.WindowStageEventType.ACTIVE: // 获焦状态 Log.i(TAG, 'windowStage active.'); if (this.stillAttachedForEvent("onWindowFocusChanged")) { + this.delegate?.getFlutterEngine()?.getTextInputChannel()?.textInputMethodHandler?.handleChangeFocus(true); this?.delegate?.onWindowFocusChanged(true); } break; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterEntry.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterEntry.ets index 124eb6488d..38f0192ea0 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterEntry.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterEntry.ets @@ -75,6 +75,7 @@ export default class FlutterEntry implements Host { break; case window.WindowStageEventType.ACTIVE: // 获焦状态 Log.i(TAG, 'windowStage active.'); + this.delegate?.getFlutterEngine()?.getTextInputChannel()?.textInputMethodHandler?.handleChangeFocus(true); this?.delegate?.onWindowFocusChanged(true); break; case window.WindowStageEventType.INACTIVE: // 失焦状态 diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets index 2d5c4ac2a3..8c75488d7a 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets @@ -22,6 +22,7 @@ import inputMethod from '@ohos.inputMethod'; import Log from '../../util/Log'; import { EditingStateWatcher, ListenableEditingState } from './ListenableEditingState'; import Any from '../common/Any'; +import { inputDevice } from '@kit.InputKit'; /// 临时规避缺少newline对应枚举问题 const NEWLINE_KEY_TYPE: number = 8; @@ -82,6 +83,7 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { private inputTypeNone: string = 'NONE'; private keyboardStatus: inputMethod.KeyboardStatus = inputMethod.KeyboardStatus.HIDE; private inputAttribute: inputMethod.InputAttribute = { textInputType: 0, enterKeyType: 1 }; + private keyboardFocusState: boolean = false constructor(plugin: TextInputPlugin | Any) { this.textConfig = { @@ -96,6 +98,7 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { /// 通过判断是否是TextInputType.none来决定是否弹出键盘 show(): void { if (this.canShowTextInput()) { + this.keyboardFocusState = true; this.showTextInput(); } else { this.hide(); @@ -103,6 +106,7 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { } hide(): void { + this.keyboardFocusState = false; this.hideTextInput(); } @@ -163,6 +167,31 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { } } + handleChangeFocus(focusState: boolean) { + try { + inputDevice.getDeviceList((Error: Error, ids: Array) => { + let isPhysicalKeyboard = false; + for (let i = 0; i < ids.length; i++) { + const type = inputDevice.getKeyboardTypeSync(ids[i]); + if (type == inputDevice.KeyboardType.ALPHABETIC_KEYBOARD || type == inputDevice.KeyboardType.DIGITAL_KEYBOARD) { + isPhysicalKeyboard = true; + break; + } + } + + if(focusState && isPhysicalKeyboard && this.keyboardFocusState) { + this.cancelListenKeyBoardEvent(); + this.inputMethodController.detach().then(async () =>{ + await this.attach(true); + this.listenKeyBoardEvent(); + }) + } + }) + } catch (error) { + Log.e(TextInputMethodHandlerImpl.TAG, `Failed to query device. Code is ${error.code}, message is ${error.message}`) + } + } + async updateAttribute(): Promise { if (this.keyboardStatus != inputMethod.KeyboardStatus.SHOW) { return; -- Gitee From fabc7dffebad5f46bad7a4252f9fc9265b98f140 Mon Sep 17 00:00:00 2001 From: hezhengyi Date: Tue, 15 Oct 2024 09:30:31 +0800 Subject: [PATCH 070/151] =?UTF-8?q?[ohos]=E9=80=82=E9=85=8D=E6=A8=A1?= =?UTF-8?q?=E6=8B=9F=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hezhengyi --- .../ohos/ohos_external_texture_gl.cpp | 35 +++++++++++-------- .../platform/ohos/ohos_xcomponent_adapter.cpp | 8 +++-- shell/platform/ohos/platform_view_ohos.cpp | 4 +-- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index fda7cae8a0..d071a58caf 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -77,16 +77,19 @@ static bool IsPixelMapYUVFormat(PIXEL_FORMAT format) format == PIXEL_FORMAT_YCBCR_P010 || format == PIXEL_FORMAT_YCRCB_P010; } - -OHOSExternalTextureGL::OHOSExternalTextureGL(int64_t id, const std::shared_ptr& ohos_surface) - : Texture(id), ohos_surface_(std::move(ohos_surface)), transform(SkMatrix::I()) +OHOSExternalTextureGL::OHOSExternalTextureGL( + int64_t id, + const std::shared_ptr& ohos_surface) + : Texture(id), + ohos_surface_(std::move(ohos_surface)), + transform(SkMatrix::I()) { state_ = AttachmentState::uninitialized; nativeImage_ = nullptr; backGroundNativeImage_ = nullptr; nativeWindow_ = nullptr; backGroundNativeWindow_ = nullptr; - eglContext_ = EGL_NO_CONTEXT; + eglContext_ = EGL_NO_CONTEXT; eglDisplay_ = EGL_NO_DISPLAY; buffer_ = nullptr; backGroundBuffer_ = nullptr; @@ -144,7 +147,13 @@ void OHOSExternalTextureGL::Attach() return; } - int32_t ret = OH_NativeImage_AttachContext(nativeImage_, texture_name_); + int32_t ret = 0; + uint64_t usage = 0; + ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, GET_USAGE, &usage); + usage |= (1ULL << 10); + ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_USAGE, usage); + + ret = OH_NativeImage_AttachContext(nativeImage_, texture_name_); if (ret != 0) { FML_LOG(ERROR) << "OHOSExternalTextureGL OH_NativeImage_AttachContext err code:" << ret; } @@ -178,8 +187,9 @@ void OHOSExternalTextureGL::Paint(PaintContext& context, } GrBackendTexture backendTexture(1, 1, GrMipMapped::kNo, textureInfo); + GrSurfaceOrigin grOrigin = isEmulator_ ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin; sk_sp image = SkImage::MakeFromTexture( - context.gr_context, backendTexture, kTopLeft_GrSurfaceOrigin, + context.gr_context, backendTexture, grOrigin, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr); if (image) { SkAutoCanvasRestore autoRestore(context.canvas, true); @@ -188,13 +198,8 @@ void OHOSExternalTextureGL::Paint(PaintContext& context, // back. OpenGL's coordinate system has Positive Y equivalent to up, while // Skia's coordinate system has Negative Y equvalent to up. // 模拟器和真机在外接纹理功能的表现不一致,需要进行适配 - if (isEmulator_) { - context.canvas->translate(bounds.x(), bounds.y()); - context.canvas->scale(bounds.width(), bounds.height()); - } else { - context.canvas->translate(bounds.x(), bounds.y() + bounds.height()); - context.canvas->scale(bounds.width(), -bounds.height()); - } + context.canvas->translate(bounds.x(), bounds.y() + bounds.height()); + context.canvas->scale(bounds.width(), -bounds.height()); if (!transform.isIdentity()) { sk_sp shader = image->makeShader( @@ -479,7 +484,7 @@ void OHOSExternalTextureGL::ProducePixelMapToBackGroundImage() uint64_t usage = 0; OH_NativeWindow_NativeWindowHandleOpt(backGroundNativeWindow_, GET_USAGE, &usage); - usage |= NATIVEBUFFER_USAGE_CPU_READ; + usage |= NATIVEBUFFER_USAGE_CPU_READ | (1ULL << 10); OH_NativeWindow_NativeWindowHandleOpt(backGroundNativeWindow_, SET_USAGE, usage); if (backGroundBuffer_ != nullptr) { @@ -605,7 +610,7 @@ void OHOSExternalTextureGL::ProducePixelMapToNativeImage() uint64_t usage = 0; OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, GET_USAGE, &usage); - usage |= NATIVEBUFFER_USAGE_CPU_READ; + usage |= NATIVEBUFFER_USAGE_CPU_READ | (1ULL << 10); OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_USAGE, usage); if (buffer_ != nullptr) { diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp index ce9b10f61d..cb0177c3c3 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.cpp +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -160,8 +160,10 @@ static int32_t SetNativeWindowOpt(OHNativeWindow* nativeWindow, int32_t width, int height) { // Set the read and write scenarios of the native window buffer. - int code = SET_USAGE; - int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, BUFFER_USAGE_MEM_DMA); + uint64_t usage = 0; + int ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, GET_USAGE, &usage); + usage |= BUFFER_USAGE_MEM_DMA | (1ULL << 10); + ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_USAGE, usage); if (ret) { LOGE( "Set NativeWindow Usage Failed :window:%{public}p ,w:%{public}d x " @@ -169,7 +171,7 @@ static int32_t SetNativeWindowOpt(OHNativeWindow* nativeWindow, nativeWindow, width, height, ret); } // Set the width and height of the native window buffer. - code = SET_BUFFER_GEOMETRY; + int code = SET_BUFFER_GEOMETRY; ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height); if (ret) { diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index bad544f3f8..956e8c03a9 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -434,7 +434,7 @@ void PlatformViewOHOS::RegisterExternalTextureByImage( iter->second->DispatchImage(image); } else { std::shared_ptr ohos_external_gl = - std::make_shared(texture_id, ohos_surface_); + std::make_shared(texture_id, ohos_surface_); external_texture_gl_[texture_id] = ohos_external_gl; RegisterTexture(ohos_external_gl); ohos_external_gl->DispatchImage(image); @@ -454,7 +454,7 @@ uint64_t PlatformViewOHOS::RegisterExternalTexture(int64_t texture_id) int ret = -1; if (ohos_context_->RenderingApi() == OHOSRenderingAPI::kOpenGLES) { std::shared_ptr ohos_external_gl = - std::make_shared(texture_id, ohos_surface_); + std::make_shared(texture_id, ohos_surface_); ohos_external_gl->nativeImage_ = OH_NativeImage_Create(texture_id, GL_TEXTURE_EXTERNAL_OES); if (ohos_external_gl->nativeImage_ == nullptr) { FML_DLOG(ERROR) << "Error with OH_NativeImage_Create"; -- Gitee From a59ae69e079a603811296abc591270070ce9ce28 Mon Sep 17 00:00:00 2001 From: asklie <760956257@qq.com> Date: Fri, 25 Oct 2024 16:25:01 +0800 Subject: [PATCH 071/151] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E4=B8=AD?= =?UTF-8?q?=E6=96=87=E6=8F=90=E7=A4=BA=E6=A1=86=E6=97=A0=E6=B3=95=E5=AE=9A?= =?UTF-8?q?=E4=BD=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: asklie <760956257@qq.com> --- .../systemchannels/TextInputChannel.ets | 96 ++++++++++++++----- .../ets/plugin/editing/TextInputPlugin.ets | 4 + 2 files changed, 76 insertions(+), 24 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets index eb6eb64f59..4e116d44bb 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets @@ -23,6 +23,8 @@ import inputMethod from '@ohos.inputMethod'; import ArrayList from '@ohos.util.ArrayList'; import { TextEditingDelta, TextEditingDeltaJson } from '../../../plugin/editing/TextEditingDelta'; import Any from '../../../plugin/common/Any'; +import { window } from '@kit.ArkUI'; +import { BusinessError } from '@kit.BasicServicesKit'; const TAG = "TextInputChannel"; /// 规避换行标识无法显示问题,api修改后再删除 @@ -47,10 +49,10 @@ export default class TextInputChannel { } createEditingStateJSON(text: string, - selectionStart: number, - selectionEnd: number, - composingStart: number, - composingEnd: number): EditingState { + selectionStart: number, + selectionEnd: number, + composingStart: number, + composingEnd: number): EditingState { let state: EditingState = { text: text, selectionBase: selectionStart, @@ -77,11 +79,11 @@ export default class TextInputChannel { * Instructs Flutter to update its text input editing state to reflect the given configuration. */ updateEditingState(inputClientId: number, - text: string, - selectionStart: number, - selectionEnd: number, - composingStart: number, - composingEnd: number): void { + text: string, + selectionStart: number, + selectionEnd: number, + composingStart: number, + composingEnd: number): void { Log.d(TAG, "updateEditingState:" + "Text: " + text + " Selection start: " + selectionStart + " Selection end: " + selectionEnd + " Composing start: " + composingStart + " Composing end: " + composingEnd); @@ -178,6 +180,8 @@ export interface TextInputMethodHandler { setEditableSizeAndTransform(width: number, height: number, transform: number[]): void; + setCursorSizeAndPosition(cursorInfo: inputMethod.CursorInfo): void; + setEditingState(editingState: TextEditState): void; clearClient(): void; @@ -201,17 +205,17 @@ export class Configuration { fields: Configuration[] = []; constructor(obscureText: boolean, - autocorrect: boolean, - enableSuggestions: boolean, - enableIMEPersonalizedLearning: boolean, - enableDeltaModel: boolean, - textCapitalization: TextCapitalization, - inputType: InputType, - inputAction: Number, - actionLabel: String, - autofill: boolean, - contentListString: [], - fields: Configuration[] + autocorrect: boolean, + enableSuggestions: boolean, + enableIMEPersonalizedLearning: boolean, + enableDeltaModel: boolean, + textCapitalization: TextCapitalization, + inputType: InputType, + inputAction: Number, + actionLabel: String, + autofill: boolean, + contentListString: [], + fields: Configuration[] ) { this.obscureText = obscureText; this.autocorrect = autocorrect; @@ -358,10 +362,10 @@ export class TextEditState { composingEnd: number; constructor(text: string, - selectionStart: number, - selectionEnd: number, - composingStart: number, - composingEnd: number) { + selectionStart: number, + selectionEnd: number, + composingStart: number, + composingEnd: number) { if ((selectionStart != -1 || selectionEnd != -1) && (selectionStart < 0 || selectionEnd < 0)) { throw new Error("invalid selection: (" + selectionStart + ", " + selectionEnd + ")"); @@ -422,11 +426,49 @@ export class TextEditState { } } +export interface offsetRect { + left: number; + top: number; + width: number; + height: number; +} + class TextInputCallback implements MethodCallHandler { textInputMethodHandler: TextInputMethodHandler; + windowPosition: offsetRect = { + left: 0, + top: 0, + width: 0, + height: 0, + }; + cursorPosition: offsetRect = { + left: 0, + top: 0, + width: 0, + height: 0, + } constructor(handler: TextInputMethodHandler) { this.textInputMethodHandler = handler; + const context = getContext(this) as Context + window.getLastWindow(context, (err: BusinessError, data) => { + this.windowPosition = data.getWindowProperties().windowRect; + data.on('windowRectChange', (rect) => { + this.windowPosition = rect.rect; + this.setCursorPosition(); + }) + }) + } + + setCursorPosition() { + const left = (this.windowPosition.left as number) + this.cursorPosition.left; + const top = (this.windowPosition.top as number) + this.cursorPosition.top; + this.textInputMethodHandler.setCursorSizeAndPosition({ + left: left, + top: top, + width: 100, + height: 50, + }) } onMethodCall(call: MethodCall, result: MethodResult) { @@ -482,6 +524,12 @@ class TextInputCallback implements MethodCallHandler { //TODO: result.notImplemented(); break; + case "TextInput.setCursorPotion": + let cursorPosition: offsetRect = args[0]; + this.cursorPosition = cursorPosition; + this.setCursorPosition(); + result.success(null); + break; default: result.notImplemented(); break; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets index 8c75488d7a..e120dfeedb 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets @@ -131,6 +131,10 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { } + setCursorSizeAndPosition(cursorInfo: inputMethod.CursorInfo) { + this.inputMethodController.updateCursor(cursorInfo) + } + setEditingState(editingState: TextEditState): void { Log.d(TextInputMethodHandlerImpl.TAG, "text:" + editingState.text + " selectionStart:" + editingState.selectionStart + " selectionEnd:" -- Gitee From b32263b35613139138468ad3b407d9eade560cb2 Mon Sep 17 00:00:00 2001 From: hezhengyi Date: Fri, 25 Oct 2024 16:48:03 +0800 Subject: [PATCH 072/151] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hezhengyi --- .../ohos/ohos_external_texture_gl.cpp | 7 ++-- .../platform/ohos/ohos_xcomponent_adapter.cpp | 42 +------------------ shell/platform/ohos/types.h | 40 ++++++++++++++++++ 3 files changed, 46 insertions(+), 43 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index d071a58caf..1f62cc2ae0 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -26,6 +26,7 @@ #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/gpu/GrBackendSurface.h" #include "third_party/skia/include/gpu/GrDirectContext.h" +#include "types.h" #define EGL_PLATFORM_OHOS_KHR 0x34E0 @@ -150,7 +151,7 @@ void OHOSExternalTextureGL::Attach() int32_t ret = 0; uint64_t usage = 0; ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, GET_USAGE, &usage); - usage |= (1ULL << 10); + usage |= (BUFFER_USAGE_HW_COMPOSER); ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_USAGE, usage); ret = OH_NativeImage_AttachContext(nativeImage_, texture_name_); @@ -484,7 +485,7 @@ void OHOSExternalTextureGL::ProducePixelMapToBackGroundImage() uint64_t usage = 0; OH_NativeWindow_NativeWindowHandleOpt(backGroundNativeWindow_, GET_USAGE, &usage); - usage |= NATIVEBUFFER_USAGE_CPU_READ | (1ULL << 10); + usage |= NATIVEBUFFER_USAGE_CPU_READ | (BUFFER_USAGE_HW_COMPOSER); OH_NativeWindow_NativeWindowHandleOpt(backGroundNativeWindow_, SET_USAGE, usage); if (backGroundBuffer_ != nullptr) { @@ -610,7 +611,7 @@ void OHOSExternalTextureGL::ProducePixelMapToNativeImage() uint64_t usage = 0; OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, GET_USAGE, &usage); - usage |= NATIVEBUFFER_USAGE_CPU_READ | (1ULL << 10); + usage |= NATIVEBUFFER_USAGE_CPU_READ | (BUFFER_USAGE_HW_COMPOSER); OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_USAGE, usage); if (buffer_ != nullptr) { diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp index cb0177c3c3..1770ab6c46 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.cpp +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -117,52 +117,14 @@ void XComponentAdapter::OnMouseWheel(std::string& id, mouseWheelEvent event) } #include -using OHOS_SurfaceBufferUsage = enum { - BUFFER_USAGE_CPU_READ = (1ULL << 0), /**< CPU read buffer */ - BUFFER_USAGE_CPU_WRITE = (1ULL << 1), /**< CPU write memory */ - BUFFER_USAGE_MEM_MMZ = (1ULL << 2), /**< Media memory zone (MMZ) */ - BUFFER_USAGE_MEM_DMA = (1ULL << 3), /**< Direct memory access (DMA) buffer */ - BUFFER_USAGE_MEM_SHARE = (1ULL << 4), /**< Shared memory buffer*/ - BUFFER_USAGE_MEM_MMZ_CACHE = (1ULL << 5), /**< MMZ with cache*/ - BUFFER_USAGE_MEM_FB = (1ULL << 6), /**< Framebuffer */ - BUFFER_USAGE_ASSIGN_SIZE = (1ULL << 7), /**< Memory assigned */ - BUFFER_USAGE_HW_RENDER = (1ULL << 8), /**< For GPU write case */ - BUFFER_USAGE_HW_TEXTURE = (1ULL << 9), /**< For GPU read case */ - BUFFER_USAGE_HW_COMPOSER = (1ULL << 10), /**< For hardware composer */ - BUFFER_USAGE_PROTECTED = - (1ULL << 11), /**< For safe buffer case, such as DRM */ - BUFFER_USAGE_CAMERA_READ = (1ULL << 12), /**< For camera read case */ - BUFFER_USAGE_CAMERA_WRITE = (1ULL << 13), /**< For camera write case */ - BUFFER_USAGE_VIDEO_ENCODER = (1ULL << 14), /**< For encode case */ - BUFFER_USAGE_VIDEO_DECODER = (1ULL << 15), /**< For decode case */ - BUFFER_USAGE_VENDOR_PRI0 = (1ULL << 44), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI1 = (1ULL << 45), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI2 = (1ULL << 46), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI3 = (1ULL << 47), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI4 = (1ULL << 48), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI5 = (1ULL << 49), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI6 = (1ULL << 50), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI7 = (1ULL << 51), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI8 = (1ULL << 52), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI9 = (1ULL << 53), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI10 = (1ULL << 54), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI11 = (1ULL << 55), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI12 = (1ULL << 56), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI13 = (1ULL << 57), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI14 = (1ULL << 58), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI15 = (1ULL << 59), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI16 = (1ULL << 60), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI17 = (1ULL << 61), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI18 = (1ULL << 62), /**< Reserverd for vendor */ - BUFFER_USAGE_VENDOR_PRI19 = (1ULL << 63), /**< Reserverd for vendor */ -}; + static int32_t SetNativeWindowOpt(OHNativeWindow* nativeWindow, int32_t width, int height) { // Set the read and write scenarios of the native window buffer. uint64_t usage = 0; int ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, GET_USAGE, &usage); - usage |= BUFFER_USAGE_MEM_DMA | (1ULL << 10); + usage |= BUFFER_USAGE_MEM_DMA | (BUFFER_USAGE_HW_COMPOSER); ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_USAGE, usage); if (ret) { LOGE( diff --git a/shell/platform/ohos/types.h b/shell/platform/ohos/types.h index 9be037096b..69fa5fd484 100644 --- a/shell/platform/ohos/types.h +++ b/shell/platform/ohos/types.h @@ -24,5 +24,45 @@ enum Locales { SCRIPT_INDEX, }; +using OHOS_SurfaceBufferUsage = enum { + BUFFER_USAGE_CPU_READ = (1ULL << 0), /**< CPU read buffer */ + BUFFER_USAGE_CPU_WRITE = (1ULL << 1), /**< CPU write memory */ + BUFFER_USAGE_MEM_MMZ = (1ULL << 2), /**< Media memory zone (MMZ) */ + BUFFER_USAGE_MEM_DMA = (1ULL << 3), /**< Direct memory access (DMA) buffer */ + BUFFER_USAGE_MEM_SHARE = (1ULL << 4), /**< Shared memory buffer*/ + BUFFER_USAGE_MEM_MMZ_CACHE = (1ULL << 5), /**< MMZ with cache*/ + BUFFER_USAGE_MEM_FB = (1ULL << 6), /**< Framebuffer */ + BUFFER_USAGE_ASSIGN_SIZE = (1ULL << 7), /**< Memory assigned */ + BUFFER_USAGE_HW_RENDER = (1ULL << 8), /**< For GPU write case */ + BUFFER_USAGE_HW_TEXTURE = (1ULL << 9), /**< For GPU read case */ + BUFFER_USAGE_HW_COMPOSER = (1ULL << 10), /**< For hardware composer */ + BUFFER_USAGE_PROTECTED = + (1ULL << 11), /**< For safe buffer case, such as DRM */ + BUFFER_USAGE_CAMERA_READ = (1ULL << 12), /**< For camera read case */ + BUFFER_USAGE_CAMERA_WRITE = (1ULL << 13), /**< For camera write case */ + BUFFER_USAGE_VIDEO_ENCODER = (1ULL << 14), /**< For encode case */ + BUFFER_USAGE_VIDEO_DECODER = (1ULL << 15), /**< For decode case */ + BUFFER_USAGE_VENDOR_PRI0 = (1ULL << 44), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI1 = (1ULL << 45), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI2 = (1ULL << 46), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI3 = (1ULL << 47), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI4 = (1ULL << 48), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI5 = (1ULL << 49), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI6 = (1ULL << 50), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI7 = (1ULL << 51), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI8 = (1ULL << 52), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI9 = (1ULL << 53), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI10 = (1ULL << 54), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI11 = (1ULL << 55), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI12 = (1ULL << 56), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI13 = (1ULL << 57), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI14 = (1ULL << 58), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI15 = (1ULL << 59), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI16 = (1ULL << 60), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI17 = (1ULL << 61), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI18 = (1ULL << 62), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI19 = (1ULL << 63), /**< Reserverd for vendor */ +}; + } // namespace flutter #endif \ No newline at end of file -- Gitee From 76ae099e319439d147e88e7ff9b964d06db1aaa7 Mon Sep 17 00:00:00 2001 From: laoguanyao <806103474@qq.com> Date: Fri, 25 Oct 2024 17:04:46 +0800 Subject: [PATCH 073/151] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=BD=AF=E9=94=AE?= =?UTF-8?q?=E7=9B=98=E7=9B=91=E5=90=AC=E4=BA=8B=E4=BB=B6=EF=BC=8C=E7=A1=AE?= =?UTF-8?q?=E4=BF=9D=E8=BD=AF=E9=94=AE=E7=9B=98=E5=8F=91=E7=94=9F=E5=8F=98?= =?UTF-8?q?=E5=8C=96=E5=90=8E=E5=8F=AF=E4=BB=A5=E6=AD=A3=E5=B8=B8=E5=88=B7?= =?UTF-8?q?=E6=96=B0FlutterView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: laoguanyao <806103474@qq.com> --- .../flutter/src/main/ets/view/FlutterView.ets | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index 3924d55c20..5af7b9cf9d 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -150,6 +150,7 @@ export class FlutterView { this.mainWindow?.on('windowSizeChange', this.windowSizeChangeCallback); this.mainWindow?.on('avoidAreaChange', this.avoidAreaChangeCallback); this.mainWindow?.on('windowStatusChange', this.windowStatusChangeCallback); + this.mainWindow?.on('keyboardHeightChange', this.keyboardHeightChangeCallback); this.systemAvoidArea = this.mainWindow?.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM); this.navigationAvoidArea = this.mainWindow?.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR); this.gestureAvoidArea = this.mainWindow?.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM_GESTURE); @@ -198,6 +199,14 @@ export class FlutterView { } }; + private keyboardHeightChangeCallback = (data: number) => { + Log.i(TAG, "keyboardHeightChangeCallback " + data); + this.keyboardAvoidArea.bottomRect.height = data; + if (this.isAttachedToFlutterEngine()) { + this.onAreaChange(null); + } + }; + getId(): string { return this.id } @@ -243,6 +252,7 @@ export class FlutterView { this.mainWindow?.off('windowSizeChange', this.windowSizeChangeCallback); this.mainWindow?.off('avoidAreaChange', this.avoidAreaChangeCallback); this.mainWindow?.off('windowStatusChange', this.windowStatusChangeCallback); + this.mainWindow?.off('keyboardHeightChange', this.keyboardHeightChangeCallback); } catch (e) { Log.e(TAG, "mainWindow off error: " + JSON.stringify(e)); } -- Gitee From 7efe5926821f2b97b257a78905c2250e688e64b1 Mon Sep 17 00:00:00 2001 From: asklie <760956257@qq.com> Date: Fri, 25 Oct 2024 19:51:35 +0800 Subject: [PATCH 074/151] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: asklie <760956257@qq.com> --- .../engine/systemchannels/TextInputChannel.ets | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets index 4e116d44bb..04458a1334 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets @@ -24,7 +24,8 @@ import ArrayList from '@ohos.util.ArrayList'; import { TextEditingDelta, TextEditingDeltaJson } from '../../../plugin/editing/TextEditingDelta'; import Any from '../../../plugin/common/Any'; import { window } from '@kit.ArkUI'; -import { BusinessError } from '@kit.BasicServicesKit'; +import { BusinessError, print } from '@kit.BasicServicesKit'; +import { Rect } from '@kit.ArkGraphics3D'; const TAG = "TextInputChannel"; /// 规避换行标识无法显示问题,api修改后再删除 @@ -186,8 +187,6 @@ export interface TextInputMethodHandler { clearClient(): void; - handleChangeFocus(focusState: boolean): void; - } export class Configuration { @@ -451,9 +450,9 @@ class TextInputCallback implements MethodCallHandler { constructor(handler: TextInputMethodHandler) { this.textInputMethodHandler = handler; const context = getContext(this) as Context - window.getLastWindow(context, (err: BusinessError, data) => { + window.getLastWindow(context, (err: BusinessError, data: window.Window) => { this.windowPosition = data.getWindowProperties().windowRect; - data.on('windowRectChange', (rect) => { + data.on('windowRectChange', (rect: window.RectChangeOptions) => { this.windowPosition = rect.rect; this.setCursorPosition(); }) @@ -521,7 +520,6 @@ class TextInputCallback implements MethodCallHandler { result.notImplemented(); break; case "TextInput.finishAutofillContext": - //TODO: result.notImplemented(); break; case "TextInput.setCursorPotion": -- Gitee From 8fd9ea592a13b89835587f3e60824d385c9434d5 Mon Sep 17 00:00:00 2001 From: asklie <760956257@qq.com> Date: Sat, 26 Oct 2024 09:32:02 +0800 Subject: [PATCH 075/151] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: asklie <760956257@qq.com> --- .../ets/embedding/engine/systemchannels/TextInputChannel.ets | 3 +++ 1 file changed, 3 insertions(+) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets index 04458a1334..ceacf9c596 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets @@ -187,6 +187,8 @@ export interface TextInputMethodHandler { clearClient(): void; + handleChangeFocus(focusState: boolean): void; + } export class Configuration { @@ -520,6 +522,7 @@ class TextInputCallback implements MethodCallHandler { result.notImplemented(); break; case "TextInput.finishAutofillContext": + //TODO: result.notImplemented(); break; case "TextInput.setCursorPotion": -- Gitee From 75e70872a7257249e3d1ff0c6e9bc11d223b6cdd Mon Sep 17 00:00:00 2001 From: asklie <760956257@qq.com> Date: Sat, 26 Oct 2024 11:08:14 +0800 Subject: [PATCH 076/151] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E6=8A=A5?= =?UTF-8?q?=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: asklie <760956257@qq.com> --- .../engine/systemchannels/TextInputChannel.ets | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets index ceacf9c596..454a589053 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets @@ -427,22 +427,15 @@ export class TextEditState { } } -export interface offsetRect { - left: number; - top: number; - width: number; - height: number; -} - class TextInputCallback implements MethodCallHandler { textInputMethodHandler: TextInputMethodHandler; - windowPosition: offsetRect = { + windowPosition: window.Rect = { left: 0, top: 0, width: 0, height: 0, }; - cursorPosition: offsetRect = { + cursorPosition: window.Rect = { left: 0, top: 0, width: 0, @@ -453,9 +446,9 @@ class TextInputCallback implements MethodCallHandler { this.textInputMethodHandler = handler; const context = getContext(this) as Context window.getLastWindow(context, (err: BusinessError, data: window.Window) => { - this.windowPosition = data.getWindowProperties().windowRect; + this.windowPosition = data.getWindowProperties().windowRect as window.Rect; data.on('windowRectChange', (rect: window.RectChangeOptions) => { - this.windowPosition = rect.rect; + this.windowPosition = rect.rect as window.Rect; this.setCursorPosition(); }) }) @@ -526,7 +519,7 @@ class TextInputCallback implements MethodCallHandler { result.notImplemented(); break; case "TextInput.setCursorPotion": - let cursorPosition: offsetRect = args[0]; + let cursorPosition: window.Rect = args[0]; this.cursorPosition = cursorPosition; this.setCursorPosition(); result.success(null); -- Gitee From 758218888deeac7a47bcb2d6791389a67965fe5f Mon Sep 17 00:00:00 2001 From: hezhengyi Date: Fri, 25 Oct 2024 17:04:21 +0800 Subject: [PATCH 077/151] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E7=9A=84=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hezhengyi --- shell/platform/ohos/ohos_external_texture_gl.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 1f62cc2ae0..374e63a1d0 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -148,13 +148,7 @@ void OHOSExternalTextureGL::Attach() return; } - int32_t ret = 0; - uint64_t usage = 0; - ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, GET_USAGE, &usage); - usage |= (BUFFER_USAGE_HW_COMPOSER); - ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_USAGE, usage); - - ret = OH_NativeImage_AttachContext(nativeImage_, texture_name_); + int32_t ret = OH_NativeImage_AttachContext(nativeImage_, texture_name_); if (ret != 0) { FML_LOG(ERROR) << "OHOSExternalTextureGL OH_NativeImage_AttachContext err code:" << ret; } @@ -416,6 +410,11 @@ void OHOSExternalTextureGL::ProduceColorToBackGroundImage(int32_t width, int32_t return; } + uint64_t usage = 0; + OH_NativeWindow_NativeWindowHandleOpt(backGroundNativeWindow_, GET_USAGE, &usage); + usage |= NATIVEBUFFER_USAGE_CPU_READ | (BUFFER_USAGE_HW_COMPOSER); + OH_NativeWindow_NativeWindowHandleOpt(backGroundNativeWindow_, SET_USAGE, usage); + ret = OH_NativeWindow_NativeWindowRequestBuffer(backGroundNativeWindow_, &backGroundBuffer_, &backGroundFenceFd); if (ret != 0) { FML_LOG(ERROR) << "OHOSExternalTextureGL::setBackground OH_NativeWindow_NativeWindowRequestBuffer err:" << ret; -- Gitee From 9a4d003a1c2681d660663001eba3ec5a8f0acf4e Mon Sep 17 00:00:00 2001 From: openharmony_ci <120357966@qq.com> Date: Thu, 24 Oct 2024 01:47:52 +0000 Subject: [PATCH 078/151] =?UTF-8?q?!510=20=E8=A7=A3=E5=86=B3getContext(thi?= =?UTF-8?q?s)=E5=AF=BC=E8=87=B4=E8=8E=B7=E5=8F=96=E7=9A=84window=E6=98=AFu?= =?UTF-8?q?ndefine=E7=9A=84=E9=97=AE=E9=A2=98=20Merge=20pull=20request=20!?= =?UTF-8?q?510=20from=20shijie/dev?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/ets/embedding/ohos/FlutterAbility.ets | 2 +- .../src/main/ets/embedding/ohos/FlutterManager.ets | 11 ++++++----- .../flutter/src/main/ets/plugin/PlatformPlugin.ets | 6 +++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets index edfb59ca4c..af3a61cd6d 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets @@ -180,7 +180,7 @@ export class FlutterAbility extends UIAbility implements Host { Log.i(TAG, 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); }); - FlutterManager.getInstance().setUseFullScreen(true); + FlutterManager.getInstance().setUseFullScreen(true, this.context); } catch (exception) { Log.e(TAG, 'Failed to enable the listener for window stage event changes. Cause:' + JSON.stringify(exception)); } diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterManager.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterManager.ets index e2ef4d772b..0f449572ed 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterManager.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterManager.ets @@ -109,8 +109,8 @@ export default class FlutterManager { return this.mFullScreenListener; } - setUseFullScreen(use: boolean) { - this.mFullScreenListener.setUseFullScreen(use) + setUseFullScreen(use: boolean, context?: Context | null | undefined) { + this.mFullScreenListener.setUseFullScreen(use, context); } useFullScreen(): boolean { @@ -120,7 +120,7 @@ export default class FlutterManager { export interface FullScreenListener { useFullScreen(): boolean; - setUseFullScreen(useFullScreen: boolean): void; + setUseFullScreen(useFullScreen: boolean, context?: Context | null | undefined): void; onScreenStateChanged(data: window.WindowStatusType): void; } @@ -132,12 +132,13 @@ export class DefaultFullScreenListener implements FullScreenListener { return this.fullScreen; } - setUseFullScreen(useFullScreen: boolean): void { + setUseFullScreen(useFullScreen: boolean, context?: Context | null | undefined): void { this.fullScreen = useFullScreen; this.skipCheck = true; + context = context??getContext(this); let window = FlutterManager.getInstance() - .getWindowStage(FlutterManager.getInstance().getUIAbility(getContext(this))); + .getWindowStage(FlutterManager.getInstance().getUIAbility(context)); window.getMainWindowSync().setWindowLayoutFullScreen(useFullScreen); Log.i(TAG, "WindowLayoutFullScreen is on") } diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/PlatformPlugin.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/PlatformPlugin.ets index 949480ec65..500390aeb9 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/PlatformPlugin.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/PlatformPlugin.ets @@ -279,13 +279,13 @@ export class PlatformPluginCallback implements PlatformMessageHandler { let uiConfig: ('status' | 'navigation')[] = []; if (mode == SystemUiMode.LEAN_BACK) { //全屏显示,通过点击显示器上的任何位置都可以显示状态和导航栏 - FlutterManager.getInstance().setUseFullScreen(true); + FlutterManager.getInstance().setUseFullScreen(true, null); } else if (mode == SystemUiMode.IMMERSIVE) { //全屏显示,通过在显示器边缘的滑动手势可以显示状态和导航栏,应用程序不会接收到此手势 - FlutterManager.getInstance().setUseFullScreen(true); + FlutterManager.getInstance().setUseFullScreen(true, null); } else if (mode == SystemUiMode.IMMERSIVE_STICKY) { //全屏显示,通过在显示器边缘的滑动手势可以显示状态和导航栏,此手势由应用程序接收 - FlutterManager.getInstance().setUseFullScreen(true); + FlutterManager.getInstance().setUseFullScreen(true, null); } else if (mode == SystemUiMode.EDGE_TO_EDGE) { uiConfig = ['status', 'navigation']; } else { -- Gitee From fc21950aef739251daa26b8afb519214c6ea7dc2 Mon Sep 17 00:00:00 2001 From: openharmony_ci <120357966@qq.com> Date: Fri, 25 Oct 2024 04:27:23 +0000 Subject: [PATCH 079/151] =?UTF-8?q?!513=20=E4=BF=AE=E6=94=B9ets=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E7=9A=84=E7=A8=B3=E5=AE=9A=E6=80=A7=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20Merge=20pull=20request=20!513=20from=20hazy/dev?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/ets/embedding/ohos/FlutterPage.ets | 2 +- .../src/main/ets/plugin/editing/TextInputPlugin.ets | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets index 1634db5f6f..de520a54ea 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets @@ -183,7 +183,7 @@ export struct FlutterPage { aboutToDisappear() { this.flutterView?.removeFirstFrameListener(this); - getContext().eventHub.off(OHOS_FLUTTER_PAGE_UPDATE) + getContext()?.eventHub.off(OHOS_FLUTTER_PAGE_UPDATE) } onFirstFrame() { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets index 8c75488d7a..4ffbbd1dbd 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets @@ -322,12 +322,12 @@ class TextInputMethodHandlerImpl implements TextInputMethodHandler { } cancelListenKeyBoardEvent(): void { - this.inputMethodController.off('insertText', this.insertTextCallback); - this.inputMethodController.off('deleteLeft', this.deleteLeftCallback); - this.inputMethodController.off('deleteRight', this.deleteRightCallback); - this.inputMethodController.off('sendFunctionKey', this.sendFunctionKeyCallback); - this.inputMethodController.off('sendKeyboardStatus', this.sendKeyboardStatusCallback); - this.inputMethodController.off('selectByRange', this.selectByRangeCallback); + this.inputMethodController?.off('insertText', this.insertTextCallback); + this.inputMethodController?.off('deleteLeft', this.deleteLeftCallback); + this.inputMethodController?.off('deleteRight', this.deleteRightCallback); + this.inputMethodController?.off('sendFunctionKey', this.sendFunctionKeyCallback); + this.inputMethodController?.off('sendKeyboardStatus', this.sendKeyboardStatusCallback); + this.inputMethodController?.off('selectByRange', this.selectByRangeCallback); this.imcFlag = false; } -- Gitee From 9051954410fb48c8dc006e72660257ee2c91279c Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 28 Oct 2024 18:04:09 +0800 Subject: [PATCH 080/151] =?UTF-8?q?refactor:=E5=B0=81=E8=A3=85native?= =?UTF-8?q?=E6=97=A0=E9=9A=9C=E7=A2=8D=E9=80=9A=E9=81=93,=E9=99=8D?= =?UTF-8?q?=E4=BD=8Ebridge=E7=B1=BB=E4=B8=AD=E4=BB=A3=E7=A0=81=E8=80=A6?= =?UTF-8?q?=E5=90=88,=E6=96=B9=E4=BE=BF=E7=BB=B4=E6=8A=A4=E6=8B=93?= =?UTF-8?q?=E5=B1=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- shell/platform/ohos/BUILD.gn | 2 + .../native_accessibility_channel.cpp | 92 ++++++++++++++++++ .../native_accessibility_channel.h | 54 +++++++++++ .../ohos_accessibility_bridge.cpp | 97 +++++++++++++------ .../accessibility/ohos_accessibility_bridge.h | 21 ++-- .../ohos_accessibility_features.cpp | 76 ++++++++------- .../ohos_accessibility_features.h | 30 +++--- .../ohos_accessibility_manager.cpp | 24 ++--- .../ohos_accessibility_manager.h | 15 +-- .../src/main/cpp/types/libflutter/index.d.ets | 2 +- .../main/ets/embedding/engine/FlutterNapi.ets | 3 +- .../ets/embedding/ohos/FlutterAbility.ets | 6 +- .../flutter/src/main/ets/view/FlutterView.ets | 2 +- .../ohos/napi/platform_view_ohos_napi.cpp | 64 ++++++++++-- .../ohos/napi/platform_view_ohos_napi.h | 12 ++- shell/platform/ohos/platform_view_ohos.cpp | 5 +- shell/platform/ohos/platform_view_ohos.h | 8 +- 17 files changed, 381 insertions(+), 132 deletions(-) create mode 100644 shell/platform/ohos/accessibility/native_accessibility_channel.cpp create mode 100644 shell/platform/ohos/accessibility/native_accessibility_channel.h diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn index 68bd4bca43..5adde6edeb 100644 --- a/shell/platform/ohos/BUILD.gn +++ b/shell/platform/ohos/BUILD.gn @@ -88,6 +88,7 @@ source_set("flutter_ohos_sources") { "./accessibility/ohos_accessibility_bridge.h", "./accessibility/ohos_accessibility_features.h", "./accessibility/ohos_accessibility_manager.h", + "./accessibility/native_accessibility_channel.h" ] #configs += [ "//flutter/shell/platform/ohos/config:gtk" ] @@ -122,6 +123,7 @@ source_set("flutter_ohos_sources") { "./accessibility/ohos_accessibility_bridge.cpp", "./accessibility/ohos_accessibility_features.cpp", "./accessibility/ohos_accessibility_manager.cpp", + "./accessibility/native_accessibility_channel.cpp" ] # Set flag to stop headers being directly included (library users should not do this) diff --git a/shell/platform/ohos/accessibility/native_accessibility_channel.cpp b/shell/platform/ohos/accessibility/native_accessibility_channel.cpp new file mode 100644 index 0000000000..4beea68300 --- /dev/null +++ b/shell/platform/ohos/accessibility/native_accessibility_channel.cpp @@ -0,0 +1,92 @@ +/* + * 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 "native_accessibility_channel.h" +#include "flutter/shell/platform/ohos/ohos_shell_holder.h" +#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" + +namespace flutter { + + NativeAccessibilityChannel::NativeAccessibilityChannel() {} + + NativeAccessibilityChannel::~NativeAccessibilityChannel() {} + + /** + * 通知flutter框架ohos平台无障碍屏幕朗读已开启 + */ + void NativeAccessibilityChannel::OnOhosAccessibilityEnabled(int64_t shellHolderId) + { + FML_DLOG(INFO) << "NativeAccessibilityChannel -> OnOhosAccessibilityEnabled"; + this->SetSemanticsEnabled(shellHolderId, true); + } + + /** + * 通知flutter框架ohos平台无障碍屏幕朗读未开启 + */ + void NativeAccessibilityChannel::OnOhosAccessibilityDisabled(int64_t shellHolderId) + { + FML_DLOG(INFO) << "NativeAccessibilityChannel -> OnOhosAccessibilityDisabled"; + this->SetSemanticsEnabled(shellHolderId, false); + + auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge->ClearFlutterSemanticsCaches(); + FML_DLOG(INFO) << "OnOhosAccessibilityDisabled -> ClearFlutterSemanticsCaches()"; + } + + /** + * Native无障碍通道传递语义感知,若开启则实时更新语义树信息 + */ + void NativeAccessibilityChannel::SetSemanticsEnabled(int64_t shellHolderId, + bool enabled) + { + FML_DLOG(INFO) << "SetSemanticsEnabled -> shellHolderId: " + << shellHolderId; + auto ohos_shell_holder = + reinterpret_cast(shellHolderId); + ohos_shell_holder->GetPlatformView()->SetSemanticsEnabled(enabled); + } + + /** + * Native无障碍通道设置无障碍特征类型,如:无障碍导航、字体加粗等 + */ + void NativeAccessibilityChannel::SetAccessibilityFeatures(int64_t shellHolderId, + int32_t flags) + { + auto ohos_shell_holder = + reinterpret_cast(shellHolderId); + ohos_shell_holder->GetPlatformView()->SetAccessibilityFeatures(flags); + } + + /** + * Native无障碍通道分发flutter屏幕语义动作,如:点击、滑动等 + */ + void NativeAccessibilityChannel::DispatchSemanticsAction( + int64_t shellHolderId, + int32_t id, + flutter::SemanticsAction action, + fml::MallocMapping args) + { + auto ohos_shell_holder = + reinterpret_cast(shellHolderId); + ohos_shell_holder->GetPlatformView()->PlatformView::DispatchSemanticsAction(id, action, fml::MallocMapping()); + } + + void NativeAccessibilityChannel::UpdateSemantics( + flutter::SemanticsNodeUpdates update, + flutter::CustomAccessibilityActionUpdates actions) + { + auto ohos_a11y_bridge = OhosAccessibilityBridge::GetInstance(); + ohos_a11y_bridge->updateSemantics(update, actions); + } +} \ No newline at end of file diff --git a/shell/platform/ohos/accessibility/native_accessibility_channel.h b/shell/platform/ohos/accessibility/native_accessibility_channel.h new file mode 100644 index 0000000000..a2e9053cfc --- /dev/null +++ b/shell/platform/ohos/accessibility/native_accessibility_channel.h @@ -0,0 +1,54 @@ +/* + * 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 OHOS_NATIVE_ACCESSIBILITY_CHANNEL_H +#define OHOS_NATIVE_ACCESSIBILITY_CHANNEL_H +#include "flutter/fml/mapping.h" +#include "flutter/lib/ui/semantics/semantics_node.h" +#include "flutter/lib/ui/semantics/custom_accessibility_action.h" +namespace flutter { + +class NativeAccessibilityChannel { + public: + NativeAccessibilityChannel(); + ~NativeAccessibilityChannel(); + + void OnOhosAccessibilityEnabled(int64_t shellHolderId); + + void OnOhosAccessibilityDisabled(int64_t shellHolderId); + + void SetSemanticsEnabled(int64_t shellHolderId, bool enabled); + + void SetAccessibilityFeatures(int64_t shellHolderId, int32_t flags); + + void DispatchSemanticsAction(int64_t shellHolderId, + int32_t id, + flutter::SemanticsAction action, + fml::MallocMapping args); + + void UpdateSemantics(flutter::SemanticsNodeUpdates update, + flutter::CustomAccessibilityActionUpdates actions); + +}; + +class AccessibilityDelegate { + public: + AccessibilityDelegate(); + ~AccessibilityDelegate(); + +}; + +} + +#endif \ No newline at end of file diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 7a8b081d9c..1b2b42df97 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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 @@ -15,6 +15,7 @@ #include "ohos_accessibility_bridge.h" #include #include +#include #include "flutter/fml/logging.h" #include "flutter/shell/common/platform_view.h" #include "flutter/shell/platform/embedder/embedder.h" @@ -26,14 +27,38 @@ namespace flutter { OhosAccessibilityBridge OhosAccessibilityBridge::bridgeInstance; -OhosAccessibilityBridge::OhosAccessibilityBridge() {}; -OhosAccessibilityBridge::~OhosAccessibilityBridge() {}; +OhosAccessibilityBridge::OhosAccessibilityBridge() {} + +OhosAccessibilityBridge::~OhosAccessibilityBridge() {} OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() { return &OhosAccessibilityBridge::bridgeInstance; } +/** + * 监听当前ohos平台是否开启无障碍屏幕朗读服务 + */ +void OhosAccessibilityBridge::OnOhosAccessibilityStateChange( + int64_t shellHolderId, + bool ohosAccessibilityEnabled) +{ + native_shell_holder_id_ = shellHolderId; + auto nativeAccessibilityChannel_ = std::make_shared(); + if (ohosAccessibilityEnabled) { + FML_DLOG(INFO) << "OnOhosAccessibilityEnabled()"; + nativeAccessibilityChannel_->OnOhosAccessibilityEnabled(native_shell_holder_id_); + } else { + FML_DLOG(INFO) << "OnOhosAccessibilityEnabled()"; + nativeAccessibilityChannel_->OnOhosAccessibilityDisabled(native_shell_holder_id_); + } +} + +void OhosAccessibilityBridge::SetNativeShellHolderId(int64_t id) +{ + this->native_shell_holder_id_ = id; +} + /** * 当页面状态更新事件,在页面转换、切换、调整大小时发送页面状态更新事件 */ @@ -144,6 +169,7 @@ void OhosAccessibilityBridge::updateSemantics( if (node.HasFlag(FLAGS_::kIsHidden)) { continue; } + // 判断flutter节点是否获焦 if (IsNodeFocusable(node)) { FML_DLOG(INFO) << "UpdateSemantics -> flutterNode is focusable, node.id=" @@ -579,7 +605,7 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( // 获取root节点的绝对坐标 auto _rootRect = GetAbsoluteScreenRect(0); - auto rootRight = _rootRect.second.first; + // auto rootRight = _rootRect.second.first; auto rootBottom = _rootRect.second.second; // 真实缩放系数 @@ -628,9 +654,11 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( << currNode.id << ", (" << newLeft << ", " << newTop << ", " << newRight << ", " << newBottom << ")}"; // 防止溢出屏幕坐标 - newTop = realParentTop - rootRight; - newBottom = realParentBottom - rootBottom; - SetAbsoluteScreenRect(currNode.id, newLeft, newTop, realParentRight, + newTop = realParentTop - rootBottom; + newBottom = realParentBottom - rootBottom; + // newTop = static_cast(newTop) % static_cast(rootBottom); + // newBottom = static_cast(newBottom) % static_cast(rootBottom); + SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); } else { SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); @@ -860,9 +888,9 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( ArkUI_AccessibleRect rect = {left, top, right, bottom}; OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect); FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> node.id= " - << flutterNode.id << " SceenRect = (" << left << ", " << top - << ", " << right << ", " << bottom << ")"; - + << flutterNode.id << " SceenRect = (" << left << ", " << top + << ", " << right << ", " << bottom << ")"; + // 配置arkui的elementinfo可操作动作属性 if (IsTextField(flutterNode)) { // 若当前flutter节点为文本输入框组件 @@ -1149,6 +1177,8 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } + auto flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); + if (mode == ArkUI_AccessibilitySearchMode:: ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { /** Search for current nodes. (mode = 0) */ @@ -1156,28 +1186,35 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( int64_t elementInfoCount = static_cast(flutterSemanticsTree_.size()); for (int64_t i = 1; i < elementInfoCount; i++) { - ArkUI_AccessibilityElementInfo* newElementInfo = + auto childNode = getOrCreateFlutterSemanticsNode(static_cast(i)); + if (IsNodeVisible(childNode)) { + ArkUI_AccessibilityElementInfo* newElementInfo = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); - FlutterNodeToElementInfoById(newElementInfo, i); + FlutterNodeToElementInfoById(newElementInfo, i); + } } } else if (mode == ArkUI_AccessibilitySearchMode:: ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS) { /** Search for parent nodes. (mode = 1) */ - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - + if (IsNodeVisible(flutterNode)) { + FlutterNodeToElementInfoById(elementInfoFromList, elementId); + } } else if (mode == ArkUI_AccessibilitySearchMode:: ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_SIBLINGS) { /** Search for sibling nodes. (mode = 2) */ - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - + if (IsNodeVisible(flutterNode)) { + FlutterNodeToElementInfoById(elementInfoFromList, elementId); + } } else if (mode == ArkUI_AccessibilitySearchMode:: ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CHILDREN) { /** Search for child nodes at the next level. (mode = 4) */ - FlutterNodeToElementInfoById(elementInfoFromList, elementId); + if (IsNodeVisible(flutterNode)) { + FlutterNodeToElementInfoById(elementInfoFromList, elementId); + } } else if ( mode == @@ -1188,13 +1225,18 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( int64_t elementInfoCount = static_cast(flutterSemanticsTree_.size()); for (int64_t i = 1; i < elementInfoCount; i++) { - ArkUI_AccessibilityElementInfo* newElementInfo = + auto childNode = getOrCreateFlutterSemanticsNode(static_cast(i)); + if (IsNodeVisible(childNode)) { + ArkUI_AccessibilityElementInfo* newElementInfo = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); - FlutterNodeToElementInfoById(newElementInfo, i); + FlutterNodeToElementInfoById(newElementInfo, i); + } } } else { - FlutterNodeToElementInfoById(elementInfoFromList, elementId); + if (IsNodeVisible(flutterNode)) { + FlutterNodeToElementInfoById(elementInfoFromList, elementId); + } } FML_DLOG(INFO) << "--- FindAccessibilityNodeInfosById is end ---"; @@ -1304,21 +1346,18 @@ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( } /** - * covert arkui-specific touch action to flutter-specific action - * and dispatch it from C++ to Dart + * 解析flutter语义动作,并通过NativAccessibilityChannel分发 */ void OhosAccessibilityBridge::DispatchSemanticsAction( int32_t id, flutter::SemanticsAction action, fml::MallocMapping args) { - auto ohos_shell_holder = - reinterpret_cast(nativeShellHolder_); - ohos_shell_holder->GetPlatformView()->PlatformView::DispatchSemanticsAction( - id, action, {}); - FML_DLOG(INFO) << "DispatchSemanticsAction -> shell_holder_id: " - << nativeShellHolder_ << " id: " << id - << " action: " << static_cast(action); + auto nativeAccessibilityChannel_ = std::make_shared(); + nativeAccessibilityChannel_->DispatchSemanticsAction(native_shell_holder_id_, + id, + action, + fml::MallocMapping()); } /** diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 602df9370b..34880ea8d6 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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 @@ -12,21 +12,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #ifndef OHOS_ACCESSIBILITY_BRIDGE_H #define OHOS_ACCESSIBILITY_BRIDGE_H #include #include #include -#include +#include #include #include #include "flutter/fml/mapping.h" #include "flutter/lib/ui/semantics/custom_accessibility_action.h" #include "flutter/lib/ui/semantics/semantics_node.h" -#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_manager.h" -#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" - +#include "native_accessibility_channel.h" namespace flutter { typedef flutter::SemanticsFlags FLAGS_; @@ -69,11 +66,16 @@ class OhosAccessibilityBridge { static OhosAccessibilityBridge* GetInstance(); - bool isOhosAccessibilityEnabled_; bool IS_FLUTTER_NAVIGATE = false; - int64_t nativeShellHolder_; + int64_t native_shell_holder_id_; ArkUI_AccessibilityProvider* provider_; + void OnOhosAccessibilityStateChange( + int64_t shellHolderId, + bool ohosAccessibilityEnabled); + + void SetNativeShellHolderId(int64_t id); + void updateSemantics(flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions); @@ -143,6 +145,8 @@ class OhosAccessibilityBridge { private: static OhosAccessibilityBridge bridgeInstance; + std::shared_ptr nativeAccessibilityChannel_; + static const int32_t ROOT_NODE_ID = 0; constexpr static const double SCROLL_EXTENT_FOR_INFINITY = 100000.0; constexpr static const double SCROLL_POSITION_CAP_FOR_INFINITY = 70000.0; @@ -151,7 +155,6 @@ class OhosAccessibilityBridge { flutter::SemanticsNode lastInputFocusedNode; flutter::SemanticsNode accessibilityFocusedNode; - std::shared_ptr ax_manager_; std::vector> parentChildIdVec; std::unordered_map flutterSemanticsTree_; std::unordered_map< diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp index caea517fee..3e0b16b1b7 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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 @@ -12,47 +12,51 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_features.h" -#include "flutter/shell/platform/ohos/ohos_shell_holder.h" +#include "ohos_accessibility_features.h" #include "flutter/fml/logging.h" +#include "flutter/shell/platform/ohos/ohos_shell_holder.h" namespace flutter { - OhosAccessibilityFeatures OhosAccessibilityFeatures::instance; +OhosAccessibilityFeatures OhosAccessibilityFeatures::instance; - OhosAccessibilityFeatures::OhosAccessibilityFeatures() {}; - OhosAccessibilityFeatures::~OhosAccessibilityFeatures() {}; - - OhosAccessibilityFeatures* OhosAccessibilityFeatures::GetInstance() { - return &OhosAccessibilityFeatures::instance; - } +OhosAccessibilityFeatures::OhosAccessibilityFeatures() {}; +OhosAccessibilityFeatures::~OhosAccessibilityFeatures() {}; - /** - * bold text for AccessibilityFeature - */ - void OhosAccessibilityFeatures::SetBoldText(double fontWeightScale, int64_t shell_holder_id) { - bool shouldBold = fontWeightScale > 1.0; +OhosAccessibilityFeatures* OhosAccessibilityFeatures::GetInstance() { + return &OhosAccessibilityFeatures::instance; +} - if (shouldBold) { - accessibilityFeatureFlags |= static_cast(flutter::AccessibilityFeatureFlag::kBoldText); - FML_DLOG(INFO) << "SetBoldText -> accessibilityFeatureFlags: "< 1.0; + + if (shouldBold) { + accessibilityFeatureFlags |= + static_cast(flutter::AccessibilityFeatureFlag::kBoldText); + FML_DLOG(INFO) << "SetBoldText -> accessibilityFeatureFlags: " + << accessibilityFeatureFlags; + } else { + accessibilityFeatureFlags &= + static_cast(flutter::AccessibilityFeatureFlag::kBoldText); + } - } else { - accessibilityFeatureFlags &= static_cast(flutter::AccessibilityFeatureFlag::kBoldText); - } + SendAccessibilityFlags(shell_holder_id); +} - SendAccessibilityFlags(shell_holder_id); - } - - /** - * send the accessibility flags to flutter dart sdk - */ - void OhosAccessibilityFeatures::SendAccessibilityFlags(int64_t shell_holder_id) { - auto ohos_shell_holder = reinterpret_cast(shell_holder_id); - ohos_shell_holder->GetPlatformView()->PlatformView::SetAccessibilityFeatures(accessibilityFeatureFlags); - FML_DLOG(INFO) << "SendAccessibilityFlags -> accessibilityFeatureFlags = " - << accessibilityFeatureFlags; - accessibilityFeatureFlags = 0; - } - -} \ No newline at end of file +/** + * send the accessibility flags to flutter dart sdk + */ +void OhosAccessibilityFeatures::SendAccessibilityFlags( + int64_t shell_holder_id) { + auto nativeAccessibilityChannel_ = std::make_shared(); + nativeAccessibilityChannel_->SetAccessibilityFeatures(shell_holder_id, accessibilityFeatureFlags); + FML_DLOG(INFO) << "SendAccessibilityFlags -> accessibilityFeatureFlags = " + << accessibilityFeatureFlags; + accessibilityFeatureFlags = 0; +} + +} // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_features.h b/shell/platform/ohos/accessibility/ohos_accessibility_features.h index 093e89ce11..af271318e1 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_features.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_features.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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 @@ -16,28 +16,28 @@ #define OHOS_ACCESSIBILITY_FEATURES_H #include #include "flutter/lib/ui/window/platform_configuration.h" +#include "native_accessibility_channel.h" #include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" namespace flutter { class OhosAccessibilityFeatures { - public: - OhosAccessibilityFeatures(); - ~OhosAccessibilityFeatures(); + public: + OhosAccessibilityFeatures(); + ~OhosAccessibilityFeatures(); - static OhosAccessibilityFeatures* GetInstance(); + static OhosAccessibilityFeatures* GetInstance(); - void SetBoldText(double fontWeightScale, int64_t shell_holder_id); - void SendAccessibilityFlags(int64_t shell_holder_id); + void SetBoldText(double fontWeightScale, int64_t shell_holder_id); + void SendAccessibilityFlags(int64_t shell_holder_id); - private: - static OhosAccessibilityFeatures instance; + private: + static OhosAccessibilityFeatures instance; + std::shared_ptr nativeAccessibilityChannel_; - // Font weight adjustment (FontWeight.Bold - FontWeight.Normal = w700 - w400 = 300) - static const int32_t BOLD_TEXT_WEIGHT_ADJUSTMENT = 300; - int32_t accessibilityFeatureFlags = 0; + int32_t accessibilityFeatureFlags = 0; }; - -} -#endif \ No newline at end of file +} // namespace flutter + +#endif \ No newline at end of file diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_manager.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_manager.cpp index 9e63609765..d88a5acaf0 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_manager.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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 @@ -12,23 +12,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_manager.h" -#include "flutter/fml/logging.h" +#include "ohos_accessibility_manager.h" namespace flutter { -OhosAccessibilityManager::OhosAccessibilityManager() {}; -OhosAccessibilityManager::~OhosAccessibilityManager() {}; -void OhosAccessibilityManager::onAccessibilityStateChanged( - bool isOhosAccessibilityEnabled) {}; +OhosAccessibilityManager::OhosAccessibilityManager() {} -void OhosAccessibilityManager::setOhosAccessibilityEnabled(bool isEnabled) { - FML_DLOG(INFO) << "OhosAccessibilityManager::setOhosAccessibilityEnabled = " - << isEnabled; +OhosAccessibilityManager::~OhosAccessibilityManager() {} + +/** + * 监听ohos平台是否开启无障碍屏幕朗读功能 + */ +void OhosAccessibilityManager::OnAccessibilityStateChanged( + bool ohosAccessibilityEnabled) {} + +void OhosAccessibilityManager::SetOhosAccessibilityEnabled(bool isEnabled) { this->isOhosAccessibilityEnabled_ = isEnabled; } -bool OhosAccessibilityManager::getOhosAccessibilityEnabled() { +bool OhosAccessibilityManager::GetOhosAccessibilityEnabled() { return this->isOhosAccessibilityEnabled_; } diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_manager.h b/shell/platform/ohos/accessibility/ohos_accessibility_manager.h index d32e76173e..3e37c59e0e 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_manager.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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 @@ -14,7 +14,7 @@ */ #ifndef OHOS_ACCESSIBILITY_MANAGER_H #define OHOS_ACCESSIBILITY_MANAGER_H - +#include namespace flutter { /** @@ -25,12 +25,13 @@ class OhosAccessibilityManager { OhosAccessibilityManager(); ~OhosAccessibilityManager(); - void onAccessibilityStateChanged(bool isOhosAccessibilityEnabled); - bool getOhosAccessibilityEnabled(); - void setOhosAccessibilityEnabled(bool isEnabled); + bool isOhosAccessibilityEnabled_; + + void OnAccessibilityStateChanged(bool ohosAccessibilityEnabled); + + bool GetOhosAccessibilityEnabled(); - private: - bool isOhosAccessibilityEnabled_ = false; + void SetOhosAccessibilityEnabled(bool isEnabled); }; } // namespace flutter diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets index 6786bedf54..3090d45f58 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets @@ -146,7 +146,7 @@ export const nativeSetTextureBufferSize: (nativeShellHolderId: number, textureId */ export const nativeSetAccessibilityFeatures: (accessibilityFeatureFlags: number, responseId: number) => void; -export const nativeAccessibilityStateChange: (state: Boolean) => void; +export const nativeAccessibilityStateChange: (nativeShellHolderId: number, state: Boolean) => void; export const nativeAnnounce: (message: string) => void; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index e95bdfbf4b..741f5a8290 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -389,7 +389,7 @@ export default class FlutterNapi { this.accessibilityDelegate.accessibilityStateChange(state); } Log.d(TAG, "accessibilityStateChange is called"); - flutter.nativeAccessibilityStateChange(state); + flutter.nativeAccessibilityStateChange(this.nativeShellHolderId!, state); } setLocalizationPlugin(localizationPlugin: LocalizationPlugin | null): void { @@ -523,6 +523,7 @@ export default class FlutterNapi { } } + //native c++ get the shell holder id getShellHolderId(): void { this.ensureRunningOnMainThread(); if (this.isAttached()) { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets index 8a336a5297..869e9148fa 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets @@ -37,7 +37,6 @@ import FlutterManager from './FlutterManager'; import { FlutterView } from '../../view/FlutterView'; import ApplicationInfoLoader from '../engine/loader/ApplicationInfoLoader'; import { accessibility } from '@kit.AccessibilityKit'; -import { AccessibilityManager } from '../../view/AccessibilityBridge'; const TAG = "FlutterAbility"; const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS'; @@ -53,7 +52,6 @@ export class FlutterAbility extends UIAbility implements Host { private flutterView: FlutterView | null = null; private mainWindow?: window.Window | null; private errorManagerId:number = 0; - private accessibilityManager?: AccessibilityManager | null; getFlutterView(): FlutterView | null { return this.flutterView; @@ -116,11 +114,9 @@ export class FlutterAbility extends UIAbility implements Host { //冷启动对os是否开启无障碍服务进行查询 let accessibilityState: boolean = accessibility.isOpenAccessibilitySync(); if(accessibilityState) { - this.delegate?.getFlutterNapi()?.setSemanticsEnabled(accessibilityState); + this.delegate?.getFlutterNapi()?.accessibilityStateChange(accessibilityState); } Log.i(TAG, `accessibility isOpen state -> ${JSON.stringify(accessibilityState)}`); - - this.accessibilityManager = new AccessibilityManager(); } onDestroy() { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index 6f682d78c2..800761001d 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -154,7 +154,7 @@ export class FlutterView { //监听系统无障碍服务状态改变 accessibility.on('accessibilityStateChange', (data: boolean) => { Log.i(TAG, `subscribe accessibility state change, result: ${JSON.stringify(data)}`); - this.flutterEngine?.getFlutterNapi()?.setSemanticsEnabled(data); + this.flutterEngine?.getFlutterNapi()?.accessibilityStateChange(data); }); this.systemAvoidArea = this.mainWindow?.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM); this.navigationAvoidArea = this.mainWindow?.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR); diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index 18977911e5..e56df51cc5 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -39,6 +39,7 @@ namespace flutter { napi_env PlatformViewOHOSNapi::env_; std::vector PlatformViewOHOSNapi::system_languages; +int64_t PlatformViewOHOSNapi::napi_shell_holder_id_; /** * @brief send empty PlatformMessage @@ -507,6 +508,15 @@ napi_value PlatformViewOHOSNapi::nativeAttach(napi_env env, } } +void PlatformViewOHOSNapi::GetShellHolderId() { + FML_DLOG(INFO) << "GetShellHolderId"; + napi_status status = fml::napi::InvokeJsMethod(env_, ref_napi_obj_, + "getShellHolderId", 0, nullptr); + if (status != napi_ok) { + FML_DLOG(ERROR) << "InvokeJsMethod getShellHolderId fail "; + } +} + /** * 加载dart工程构建产物 */ @@ -1836,6 +1846,7 @@ napi_value PlatformViewOHOSNapi::nativeUpdateCustomAccessibilityActions( return nullptr; } + /** * 监听获取系统的无障碍服务是否开启 */ @@ -1843,8 +1854,8 @@ napi_value PlatformViewOHOSNapi::nativeAccessibilityStateChange( napi_env env, napi_callback_info info) { napi_status ret; - size_t argc = 1; - napi_value args[1] = {nullptr}; + size_t argc = 2; + napi_value args[2] = {nullptr}; ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); if (ret != napi_ok) { FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeAccessibilityStateChange " @@ -1852,8 +1863,16 @@ napi_value PlatformViewOHOSNapi::nativeAccessibilityStateChange( << ret; return nullptr; } + int64_t shell_holder_id; + ret = napi_get_value_int64(env, args[0], &shell_holder_id); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeAccessibilityStateChange " + "napi_get_value_int64 error:" + << ret; + return nullptr; + } bool state = false; - ret = napi_get_value_bool(env, args[0], &state); + ret = napi_get_value_bool(env, args[1], &state); if (ret != napi_ok) { FML_DLOG(ERROR) << "PlatformViewOHOSNapi::nativeAccessibilityStateChange " "napi_get_value_bool error:" @@ -1864,10 +1883,12 @@ napi_value PlatformViewOHOSNapi::nativeAccessibilityStateChange( "PlatformViewOHOSNapi::nativeAccessibilityStateChange state is: " "%{public}s", (state ? "true" : "false")); - // 传递到无障碍管理类 - auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); - ohosAccessibilityBridge->isOhosAccessibilityEnabled_ = state; + //send to accessibility bridge + auto a11y_bridge = OhosAccessibilityBridge::GetInstance(); + a11y_bridge->OnOhosAccessibilityStateChange(shell_holder_id, state); + FML_DLOG(INFO) << "nativeAccessibilityStateChange: state=" << state + << " shell_holder_id=" << shell_holder_id; return nullptr; } @@ -1932,7 +1953,7 @@ napi_value PlatformViewOHOSNapi::nativeSetSemanticsEnabled(napi_env env, napi_ca //给无障碍bridge传递nativeShellHolderId auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); - ohosAccessibilityBridge->nativeShellHolder_ = shell_holder; + ohosAccessibilityBridge->native_shell_holder_id_ = shell_holder; FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeSetSemanticsEnabled -> shell_holder:"<nativeShellHolder_ = shell_holder; - FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeGetShellHolderId -> shell_holder:"< shell_holder:"<GetPlatformView()->SetSemanticsEnabled(enabled); +} + +void PlatformViewOHOSNapi::DispatchSemanticsAction( + int64_t shell_holder, + int32_t id, + flutter::SemanticsAction action, + fml::MallocMapping args) +{ + OHOS_SHELL_HOLDER->GetPlatformView()->PlatformView::DispatchSemanticsAction(id, action, fml::MallocMapping()); +} + +void PlatformViewOHOSNapi::SetAccessibilityFeatures(int64_t shell_holder, + int32_t flags) +{ + OHOS_SHELL_HOLDER->GetPlatformView()->SetAccessibilityFeatures(flags); +} + napi_value PlatformViewOHOSNapi::nativeLookupCallbackInformation(napi_env env, napi_callback_info info) { napi_value result; diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h index f1aeac3bb5..8c576f3403 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.h +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -28,7 +28,6 @@ #include "flutter/shell/common/run_configuration.h" #include "flutter/shell/platform/ohos/napi_common.h" #include "napi/native_api.h" -#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_features.h" // class for all c++ to call js function @@ -87,6 +86,16 @@ class PlatformViewOHOSNapi { void FlutterViewOnTouchEvent(std::shared_ptr touchPacketString, int size); + /** + * accessibility-relevant interfaces + */ + void GetShellHolderId(); + void SetSemanticsEnabled(int64_t shell_hoder, bool enabled); + void SetAccessibilityFeatures(int64_t shell_hoder, int32_t flags); + void DispatchSemanticsAction(int64_t shell_hoder, + int32_t id, + flutter::SemanticsAction action, + fml::MallocMapping args); static napi_value nativeUpdateRefreshRate( napi_env env, @@ -236,6 +245,7 @@ class PlatformViewOHOSNapi { napi_ref ref_napi_obj_; static std::vector system_languages; fml::RefPtr platform_task_runner_; + static int64_t napi_shell_holder_id_; }; } // namespace flutter diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index 212c3274ec..9ed695758f 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -25,7 +25,6 @@ #include "ohos_external_texture_gl.h" #include "ohos_logging.h" #include "flutter/shell/platform/ohos/platform_view_ohos_delegate.h" - #include namespace flutter { @@ -300,8 +299,8 @@ void PlatformViewOHOS::UpdateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { FML_DLOG(INFO) << "PlatformViewOHOS::UpdateSemantics is called"; - auto ax_bridge_delegate_ = OhosAccessibilityBridge::GetInstance(); - ax_bridge_delegate_->updateSemantics(update, actions); + auto nativeAccessibilityChannel_ = std::make_shared(); + nativeAccessibilityChannel_->UpdateSemantics(update, actions); } // |PlatformView| diff --git a/shell/platform/ohos/platform_view_ohos.h b/shell/platform/ohos/platform_view_ohos.h index dac7916885..cca65a2fc5 100644 --- a/shell/platform/ohos/platform_view_ohos.h +++ b/shell/platform/ohos/platform_view_ohos.h @@ -36,7 +36,8 @@ #include "flutter/shell/platform/ohos/surface/ohos_surface.h" #include "flutter/shell/platform/ohos/vsync_waiter_ohos.h" #include "flutter/shell/platform/ohos/platform_view_ohos_delegate.h" -#include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" +#include "flutter/shell/platform/ohos/accessibility/native_accessibility_channel.h" + namespace flutter { class OhosSurfaceFactoryImpl : public OhosSurfaceFactory { @@ -135,6 +136,9 @@ class PlatformViewOHOS final : public PlatformView { const std::shared_ptr napi_facade_; std::shared_ptr ohos_context_; + std::shared_ptr platform_view_ohos_delegate_; + NativeAccessibilityChannel nativeAccessibilityChannel_; + std::shared_ptr ohos_surface_; std::shared_ptr platform_message_handler_; @@ -142,8 +146,6 @@ class PlatformViewOHOS final : public PlatformView { std::map> external_texture_gl_; std::map contextDatas_; - std::shared_ptr platform_view_ohos_delegate_; - std::atomic isDestroyed_; bool GetDestroyed(); -- Gitee From 359d7726e7040e4ae76919bedc32d3c0fc5e44e5 Mon Sep 17 00:00:00 2001 From: asklie <760956257@qq.com> Date: Tue, 29 Oct 2024 09:31:26 +0800 Subject: [PATCH 081/151] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=AD=E6=96=87?= =?UTF-8?q?=E8=BE=93=E5=85=A5=E6=B3=95=E6=8F=90=E7=A4=BA=E6=A1=86=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: asklie <760956257@qq.com> --- .../systemchannels/TextInputChannel.ets | 82 +++++++++++-------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets index 454a589053..99a9d4f39c 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets @@ -23,9 +23,9 @@ import inputMethod from '@ohos.inputMethod'; import ArrayList from '@ohos.util.ArrayList'; import { TextEditingDelta, TextEditingDeltaJson } from '../../../plugin/editing/TextEditingDelta'; import Any from '../../../plugin/common/Any'; +import { display } from '@kit.ArkUI' import { window } from '@kit.ArkUI'; import { BusinessError, print } from '@kit.BasicServicesKit'; -import { Rect } from '@kit.ArkGraphics3D'; const TAG = "TextInputChannel"; /// 规避换行标识无法显示问题,api修改后再删除 @@ -50,10 +50,10 @@ export default class TextInputChannel { } createEditingStateJSON(text: string, - selectionStart: number, - selectionEnd: number, - composingStart: number, - composingEnd: number): EditingState { + selectionStart: number, + selectionEnd: number, + composingStart: number, + composingEnd: number): EditingState { let state: EditingState = { text: text, selectionBase: selectionStart, @@ -80,11 +80,11 @@ export default class TextInputChannel { * Instructs Flutter to update its text input editing state to reflect the given configuration. */ updateEditingState(inputClientId: number, - text: string, - selectionStart: number, - selectionEnd: number, - composingStart: number, - composingEnd: number): void { + text: string, + selectionStart: number, + selectionEnd: number, + composingStart: number, + composingEnd: number): void { Log.d(TAG, "updateEditingState:" + "Text: " + text + " Selection start: " + selectionStart + " Selection end: " + selectionEnd + " Composing start: " + composingStart + " Composing end: " + composingEnd); @@ -206,17 +206,17 @@ export class Configuration { fields: Configuration[] = []; constructor(obscureText: boolean, - autocorrect: boolean, - enableSuggestions: boolean, - enableIMEPersonalizedLearning: boolean, - enableDeltaModel: boolean, - textCapitalization: TextCapitalization, - inputType: InputType, - inputAction: Number, - actionLabel: String, - autofill: boolean, - contentListString: [], - fields: Configuration[] + autocorrect: boolean, + enableSuggestions: boolean, + enableIMEPersonalizedLearning: boolean, + enableDeltaModel: boolean, + textCapitalization: TextCapitalization, + inputType: InputType, + inputAction: Number, + actionLabel: String, + autofill: boolean, + contentListString: [], + fields: Configuration[] ) { this.obscureText = obscureText; this.autocorrect = autocorrect; @@ -363,10 +363,10 @@ export class TextEditState { composingEnd: number; constructor(text: string, - selectionStart: number, - selectionEnd: number, - composingStart: number, - composingEnd: number) { + selectionStart: number, + selectionEnd: number, + composingStart: number, + composingEnd: number) { if ((selectionStart != -1 || selectionEnd != -1) && (selectionStart < 0 || selectionEnd < 0)) { throw new Error("invalid selection: (" + selectionStart + ", " + selectionEnd + ")"); @@ -441,7 +441,13 @@ class TextInputCallback implements MethodCallHandler { width: 0, height: 0, } - + devicePixelRatio = display.getDefaultDisplaySync()?.densityPixels as number; + inputPosotion: window.Rect = { + left: 0, + top: 0, + width: 0, + height: 0, + } constructor(handler: TextInputMethodHandler) { this.textInputMethodHandler = handler; const context = getContext(this) as Context @@ -452,11 +458,12 @@ class TextInputCallback implements MethodCallHandler { this.setCursorPosition(); }) }) + } setCursorPosition() { - const left = (this.windowPosition.left as number) + this.cursorPosition.left; - const top = (this.windowPosition.top as number) + this.cursorPosition.top; + const left = (this.windowPosition.left as number) + (this.cursorPosition.left + this.inputPosotion.left) * this.devicePixelRatio; + const top = (this.windowPosition.top as number) + (this.cursorPosition.top + this.inputPosotion.top) * this.devicePixelRatio; this.textInputMethodHandler.setCursorSizeAndPosition({ left: left, top: top, @@ -465,6 +472,7 @@ class TextInputCallback implements MethodCallHandler { }) } + onMethodCall(call: MethodCall, result: MethodResult) { if (this.textInputMethodHandler == null) { return; @@ -502,9 +510,17 @@ class TextInputCallback implements MethodCallHandler { this.textInputMethodHandler.setEditingState(TextEditState.fromJson(args)); result.success(null); break; + case "TextInput.setCaretRect": + this.cursorPosition.top = args.get('y'); + this.cursorPosition.left = args.get('x'); + this.cursorPosition.width = args.get('width'); + this.cursorPosition.height = args.get('height'); + this.setCursorPosition(); + break; case "TextInput.setEditableSizeAndTransform": - //TODO: - result.notImplemented(); + this.inputPosotion.left = args.get('transform')[12]; + this.inputPosotion.top = args.get('transform')[13]; + this.setCursorPosition(); break; case "TextInput.clearClient": this.textInputMethodHandler.clearClient(); @@ -518,12 +534,6 @@ class TextInputCallback implements MethodCallHandler { //TODO: result.notImplemented(); break; - case "TextInput.setCursorPotion": - let cursorPosition: window.Rect = args[0]; - this.cursorPosition = cursorPosition; - this.setCursorPosition(); - result.success(null); - break; default: result.notImplemented(); break; -- Gitee From c9ec88cc4374eecedf4868ecc7f2054ee6164934 Mon Sep 17 00:00:00 2001 From: changleipeng Date: Mon, 21 Oct 2024 17:18:57 +0800 Subject: [PATCH 082/151] test Signed-off-by: changleipeng --- BUILD.gn | 6 ++ shell/platform/ohos/BUILD.gn | 15 +++ .../ohos_surface_gl_skia_unittests.cpp | 102 ++++++++++++++++++ .../ohos_surface_software_unittests.cpp | 65 +++++++++++ .../ohos_touch_processor_unittests.cpp | 62 +++++++++++ .../ohos_xcomponent_adapter_unittests.cpp | 35 ++++++ .../testing/vsync_waiter_ohos_unittests.cpp | 48 +++++++++ 7 files changed, 333 insertions(+) create mode 100644 shell/platform/ohos/testing/ohos_surface_gl_skia_unittests.cpp create mode 100644 shell/platform/ohos/testing/ohos_surface_software_unittests.cpp create mode 100644 shell/platform/ohos/testing/ohos_touch_processor_unittests.cpp create mode 100644 shell/platform/ohos/testing/ohos_xcomponent_adapter_unittests.cpp create mode 100644 shell/platform/ohos/testing/vsync_waiter_ohos_unittests.cpp diff --git a/BUILD.gn b/BUILD.gn index 7a102d594b..773b42acf8 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -162,6 +162,12 @@ group("unittests") { "//flutter/third_party/txt:txt_unittests", ] + if (is_ohos) { + public_deps += [ + "//flutter/shell/platform/ohos:flutter_ohos_unittests", + ] + } + # The accessibility library only supports Mac and Windows at the moment. if (is_mac || is_win) { public_deps += diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn index c8e36f5796..ff52f307f0 100644 --- a/shell/platform/ohos/BUILD.gn +++ b/shell/platform/ohos/BUILD.gn @@ -176,10 +176,16 @@ executable("flutter_ohos_unittests") { sources = [ #"testing/mock_texture_registrar.cc", + "testing/ohos_surface_gl_skia_unittests.cpp", + "testing/ohos_surface_software_unittests.cpp", + "testing/ohos_touch_processor_unittests.cpp", + "testing/ohos_xcomponent_adapter_unittests.cpp", + "testing/vsync_waiter_ohos_unittests.cpp", ] public_configs = [ "//flutter:config" ] + cflags = ["-Wno-deprecated-declarations"] defines = [ "FLUTTER_ENGINE_NO_PROTOTYPES", @@ -197,6 +203,15 @@ executable("flutter_ohos_unittests") { "//flutter/shell/platform/embedder:embedder_test_utils", "//flutter/testing", ] + + ldflags = ["-lace_ndk.z"] + ldflags += ["-lnative_window"] + ldflags += ["-lnative_vsync"] + ldflags += ["-limage_ndk.z"] + ldflags += ["-lrawfile.z"] + ldflags += ["-lnative_image"] + ldflags += ["-lpixelmap_ndk.z"] + ldflags += ["-lqos"] } shared_library("flutter_shell_native") { diff --git a/shell/platform/ohos/testing/ohos_surface_gl_skia_unittests.cpp b/shell/platform/ohos/testing/ohos_surface_gl_skia_unittests.cpp new file mode 100644 index 0000000000..f1d98fb765 --- /dev/null +++ b/shell/platform/ohos/testing/ohos_surface_gl_skia_unittests.cpp @@ -0,0 +1,102 @@ +/* + * 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 +#include +#include + +#include "flutter/common/task_runners.h" +#include "flutter/fml/message_loop.h" +#include "flutter/shell/common/thread_host.h" +#include "flutter/shell/platform/ohos/ohos_context_gl_skia.h" +#include "flutter/shell/platform/ohos/ohos_surface_gl_skia.h" +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { +namespace { +TaskRunners CreateTaskRunners(const std::string& threadLabel) +{ + fml::MessageLoop::EnsureInitializedForCurrentThread(); + auto& loop = fml::MessageLoop::GetCurrent(); + return { + threadLabel, + loop.GetTaskRunner(), // platform + loop.GetTaskRunner(), // raster + loop.GetTaskRunner(), // ui + loop.GetTaskRunner() // io + }; +} + +std::unique_ptr CreateOhosContext() +{ + auto environment = fml::MakeRefCounted(); + std::string threadLabel = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + TaskRunners task_runners = CreateTaskRunners(threadLabel); + return std::make_unique(OHOSRenderingAPI::kOpenGLES, environment, task_runners, 0); +} +} // namespace + +TEST(OhosSurfaceGLSkiaTest, Create) +{ + std::shared_ptr context = CreateOhosContext(); + EXPECT_TRUE(context != nullptr); + std::unique_ptr surfaceGL = std::make_unique(context); + EXPECT_TRUE(surfaceGL != nullptr); + EXPECT_TRUE(surfaceGL->IsValid()); +} + +TEST(OhosSurfaceGLSkiaTest, ResourceContext) +{ + std::shared_ptr context = CreateOhosContext(); + EXPECT_TRUE(context != nullptr); + + std::unique_ptr surfaceGL = std::make_unique(context); + EXPECT_TRUE(surfaceGL != nullptr); + EXPECT_TRUE(surfaceGL->IsValid()); + + EXPECT_TRUE(surfaceGL->ResourceContextMakeCurrent()); + EXPECT_TRUE(surfaceGL->ResourceContextClearCurrent()); +} + +TEST(OhosSurfaceGLSkiaTest, GetContext) +{ + std::shared_ptr context = CreateOhosContext(); + EXPECT_TRUE(context != nullptr); + std::unique_ptr surfaceGL = std::make_unique(context); + EXPECT_TRUE(surfaceGL != nullptr); + EXPECT_TRUE(surfaceGL->IsValid()); + + EXPECT_TRUE(surfaceGL->CreateSnapshotSurface() != nullptr); + + std::unique_ptr result = surfaceGL->GLContextMakeCurrent(); + EXPECT_TRUE(result != nullptr); + + SurfaceFrame::FramebufferInfo info = surfaceGL->GLContextFramebufferInfo(); + EXPECT_TRUE(info.supports_readback == true); + + std::optional frameDamage(SkIRect::MakeEmpty()); + std::optional bufferDamage(SkIRect::MakeEmpty()); + GLPresentInfo presentInfo = {0, frameDamage, std::nullopt, bufferDamage}; + EXPECT_TRUE(surfaceGL->GLContextPresent(presentInfo)); + + GLFrameInfo frameInfo; + EXPECT_TRUE(surfaceGL->GLContextFBO(frameInfo).fbo_id == 0); + + sk_sp grInterface = surfaceGL->GetGLInterface(); + EXPECT_TRUE(grInterface != nullptr); +} +} +} \ No newline at end of file diff --git a/shell/platform/ohos/testing/ohos_surface_software_unittests.cpp b/shell/platform/ohos/testing/ohos_surface_software_unittests.cpp new file mode 100644 index 0000000000..c84c182661 --- /dev/null +++ b/shell/platform/ohos/testing/ohos_surface_software_unittests.cpp @@ -0,0 +1,65 @@ +/* + * 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 +#include +#include + +#include "flutter/shell/platform/ohos/ohos_surface_software.h" +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { +namespace { +std::shared_ptr CreateOhosContext() +{ + return std::make_shared(OHOSRenderingAPI::kSoftware); +} +} // namespace + +TEST(OHOSSurfaceSoftwareTest, Create) +{ + std::shared_ptr context = CreateOhosContext(); + EXPECT_TRUE(context != nullptr); + std::unique_ptr surfaceSoftWare = std::make_unique(context); + EXPECT_TRUE(surfaceSoftWare != nullptr); + EXPECT_TRUE(surfaceSoftWare->IsValid()); +} + +TEST(OHOSSurfaceSoftwareTest, CreateGPUSurface) +{ + std::shared_ptr context = CreateOhosContext(); + EXPECT_TRUE(context != nullptr); + std::unique_ptr surfaceSoftWare = std::make_unique(context); + EXPECT_TRUE(surfaceSoftWare != nullptr); + + sk_sp grContext = GrDirectContext::MakeMock(nullptr); + std::unique_ptr gpuSurface = surfaceSoftWare->CreateGPUSurface(grContext.get()); + EXPECT_TRUE(gpuSurface != nullptr); +} + +TEST(OHOSSurfaceSoftwareTest, AcquireBackingStore) +{ + std::shared_ptr context = CreateOhosContext(); + EXPECT_TRUE(context != nullptr); + std::unique_ptr surfaceSoftWare = std::make_unique(context); + EXPECT_TRUE(surfaceSoftWare != nullptr); + EXPECT_TRUE(surfaceSoftWare->IsValid()); + + sk_sp skSurface = surfaceSoftWare->AcquireBackingStore({100, 100}); + EXPECT_TRUE(skSurface != nullptr); +} +} +} \ No newline at end of file diff --git a/shell/platform/ohos/testing/ohos_touch_processor_unittests.cpp b/shell/platform/ohos/testing/ohos_touch_processor_unittests.cpp new file mode 100644 index 0000000000..c9b2a74de2 --- /dev/null +++ b/shell/platform/ohos/testing/ohos_touch_processor_unittests.cpp @@ -0,0 +1,62 @@ +/* + * 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 +#include +#include + +#include "flutter/shell/platform/ohos/ohos_touch_processor.h" +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { + +TEST(OhosTouchProcessorTest, getPointerChangeForAction) +{ + OhosTouchProcessor touchProcessor; + int maskedAction = OH_NATIVEXCOMPONENT_DOWN; + EXPECT_EQ(touchProcessor.getPointerChangeForAction(maskedAction), PointerData::Change::kDown); + maskedAction = OH_NATIVEXCOMPONENT_UP; + EXPECT_EQ(touchProcessor.getPointerChangeForAction(maskedAction), PointerData::Change::kUp); + maskedAction = OH_NATIVEXCOMPONENT_MOVE; + EXPECT_EQ(touchProcessor.getPointerChangeForAction(maskedAction), PointerData::Change::kMove); + maskedAction = OH_NATIVEXCOMPONENT_CANCEL; + EXPECT_EQ(touchProcessor.getPointerChangeForAction(maskedAction), PointerData::Change::kCancel); +} + +TEST(OhosTouchProcessorTest, getPointerDeviceTypeForToolType) +{ + OhosTouchProcessor touchProcessor; + int toolType = OH_NATIVEXCOMPONENT_TOOL_TYPE_FINGER; + EXPECT_EQ(touchProcessor.getPointerDeviceTypeForToolType(toolType), PointerData::DeviceKind::kTouch); + toolType = OH_NATIVEXCOMPONENT_TOOL_TYPE_PEN; + EXPECT_EQ(touchProcessor.getPointerDeviceTypeForToolType(toolType), PointerData::DeviceKind::kStylus); + toolType = OH_NATIVEXCOMPONENT_TOOL_TYPE_RUBBER; + EXPECT_EQ(touchProcessor.getPointerDeviceTypeForToolType(toolType), PointerData::DeviceKind::kInvertedStylus); + toolType = OH_NATIVEXCOMPONENT_TOOL_TYPE_BRUSH; + EXPECT_EQ(touchProcessor.getPointerDeviceTypeForToolType(toolType), PointerData::DeviceKind::kStylus); + toolType = OH_NATIVEXCOMPONENT_TOOL_TYPE_PENCIL; + EXPECT_EQ(touchProcessor.getPointerDeviceTypeForToolType(toolType), PointerData::DeviceKind::kStylus); + toolType = OH_NATIVEXCOMPONENT_TOOL_TYPE_AIRBRUSH; + EXPECT_EQ(touchProcessor.getPointerDeviceTypeForToolType(toolType), PointerData::DeviceKind::kStylus); + toolType = OH_NATIVEXCOMPONENT_TOOL_TYPE_MOUSE; + EXPECT_EQ(touchProcessor.getPointerDeviceTypeForToolType(toolType), PointerData::DeviceKind::kMouse); + toolType = OH_NATIVEXCOMPONENT_TOOL_TYPE_LENS; + EXPECT_EQ(touchProcessor.getPointerDeviceTypeForToolType(toolType), PointerData::DeviceKind::kTouch); + toolType = OH_NATIVEXCOMPONENT_TOOL_TYPE_UNKNOWN; + EXPECT_EQ(touchProcessor.getPointerDeviceTypeForToolType(toolType), PointerData::DeviceKind::kTouch); +} +} +} \ No newline at end of file diff --git a/shell/platform/ohos/testing/ohos_xcomponent_adapter_unittests.cpp b/shell/platform/ohos/testing/ohos_xcomponent_adapter_unittests.cpp new file mode 100644 index 0000000000..aa1538956c --- /dev/null +++ b/shell/platform/ohos/testing/ohos_xcomponent_adapter_unittests.cpp @@ -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. + */ +#include +#include +#include +#include + +#include "flutter/shell/platform/ohos/ohos_xcomponent_adapter.h" +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { +TEST(XComponentAdapterTest, SetNativeXComponent) +{ + XComponentAdapter* xcomponentAdapter = XComponentAdapter::GetInstance(); + std::string id = "test"; + OH_NativeXComponent* nativeXComponent = nullptr; + xcomponentAdapter->SetNativeXComponent(id, nativeXComponent); + + EXPECT_TRUE(xcomponentAdapter->xcomponetMap_.size() > 0); +} +} +} diff --git a/shell/platform/ohos/testing/vsync_waiter_ohos_unittests.cpp b/shell/platform/ohos/testing/vsync_waiter_ohos_unittests.cpp new file mode 100644 index 0000000000..48245deba3 --- /dev/null +++ b/shell/platform/ohos/testing/vsync_waiter_ohos_unittests.cpp @@ -0,0 +1,48 @@ +/* + * 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 +#include +#include + +#include "flutter/common/task_runners.h" +#include "flutter/shell/platform/ohos/vsync_waiter_ohos.h" +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { +namespace { +TaskRunners CreateTaskRunners(const std::string& threadLabel) +{ + fml::MessageLoop::EnsureInitializedForCurrentThread(); + auto& loop = fml::MessageLoop::GetCurrent(); + return { + threadLabel, + loop.GetTaskRunner(), // platform + loop.GetTaskRunner(), // raster + loop.GetTaskRunner(), // ui + loop.GetTaskRunner() // io + }; +} +} +TEST(VsyncWaiterOHOSTest, Create) +{ + std::string threadLabel = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + TaskRunners runners = CreateTaskRunners(threadLabel); + std::shared_ptr waiter = std::make_shared(runners); + EXPECT_TRUE(waiter != nullptr); +} +} +} \ No newline at end of file -- Gitee From 4e072343ed8c79e10fc55dffe6ac9097ba63ff49 Mon Sep 17 00:00:00 2001 From: changleipeng Date: Mon, 21 Oct 2024 17:18:57 +0800 Subject: [PATCH 083/151] test Signed-off-by: changleipeng --- BUILD.gn | 6 + shell/platform/ohos/BUILD.gn | 16 +++ .../ohos_assert_provider_unittests.cpp | 34 +++++ .../ohos_context_gl_skia_uinttests.cpp | 105 ++++++++++++++++ .../ohos/testing/ohos_display_uinttests.cpp | 34 +++++ .../testing/ohos_egl_surface_unittests.cpp | 116 ++++++++++++++++++ .../testing/ohos_environment_gl_unittests.cpp | 32 +++++ .../ohos_external_texture_gl_unittests.cpp | 60 +++++++++ 8 files changed, 403 insertions(+) create mode 100644 shell/platform/ohos/testing/ohos_assert_provider_unittests.cpp create mode 100644 shell/platform/ohos/testing/ohos_context_gl_skia_uinttests.cpp create mode 100644 shell/platform/ohos/testing/ohos_display_uinttests.cpp create mode 100644 shell/platform/ohos/testing/ohos_egl_surface_unittests.cpp create mode 100644 shell/platform/ohos/testing/ohos_environment_gl_unittests.cpp create mode 100644 shell/platform/ohos/testing/ohos_external_texture_gl_unittests.cpp diff --git a/BUILD.gn b/BUILD.gn index 7a102d594b..773b42acf8 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -162,6 +162,12 @@ group("unittests") { "//flutter/third_party/txt:txt_unittests", ] + if (is_ohos) { + public_deps += [ + "//flutter/shell/platform/ohos:flutter_ohos_unittests", + ] + } + # The accessibility library only supports Mac and Windows at the moment. if (is_mac || is_win) { public_deps += diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn index c8e36f5796..5b3345eb2c 100644 --- a/shell/platform/ohos/BUILD.gn +++ b/shell/platform/ohos/BUILD.gn @@ -176,10 +176,17 @@ executable("flutter_ohos_unittests") { sources = [ #"testing/mock_texture_registrar.cc", + "testing/ohos_assert_provider_unittests.cpp", + "testing/ohos_context_gl_skia_uinttests.cpp", + "testing/ohos_display_uinttests.cpp", + "testing/ohos_egl_surface_unittests.cpp", + "testing/ohos_environment_gl_unittests.cpp", + "testing/ohos_external_texture_gl_unittests.cpp", ] public_configs = [ "//flutter:config" ] + cflags = ["-Wno-deprecated-declarations"] defines = [ "FLUTTER_ENGINE_NO_PROTOTYPES", @@ -197,6 +204,15 @@ executable("flutter_ohos_unittests") { "//flutter/shell/platform/embedder:embedder_test_utils", "//flutter/testing", ] + + ldflags = ["-lace_ndk.z"] + ldflags += ["-lnative_window"] + ldflags += ["-lnative_vsync"] + ldflags += ["-limage_ndk.z"] + ldflags += ["-lrawfile.z"] + ldflags += ["-lnative_image"] + ldflags += ["-lpixelmap_ndk.z"] + ldflags += ["-lqos"] } shared_library("flutter_shell_native") { diff --git a/shell/platform/ohos/testing/ohos_assert_provider_unittests.cpp b/shell/platform/ohos/testing/ohos_assert_provider_unittests.cpp new file mode 100644 index 0000000000..c9a810e5da --- /dev/null +++ b/shell/platform/ohos/testing/ohos_assert_provider_unittests.cpp @@ -0,0 +1,34 @@ +/* + * 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 +#include +#include +#include + +#include "flutter/shell/platform/ohos/ohos_asset_provider.h" +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { +TEST(OHOSAssetProviderTest, Create001) +{ + std::shared_ptr provider = std::make_shared(nullptr); + EXPECT_TRUE(provider.get() != nullptr); + std::unique_ptr newProvider = provider->Clone(); + EXPECT_TRUE(newProvider.get() != nullptr); +} +} +} \ No newline at end of file diff --git a/shell/platform/ohos/testing/ohos_context_gl_skia_uinttests.cpp b/shell/platform/ohos/testing/ohos_context_gl_skia_uinttests.cpp new file mode 100644 index 0000000000..c6c129c0a3 --- /dev/null +++ b/shell/platform/ohos/testing/ohos_context_gl_skia_uinttests.cpp @@ -0,0 +1,105 @@ +/* + * 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 +#include +#include + +#include "flutter/common/task_runners.h" +#include "flutter/shell/common/thread_host.h" +#include "flutter/shell/platform/ohos/ohos_context_gl_skia.h" +#include "flutter/shell/platform/ohos/ohos_egl_surface.h" +#include "flutter/shell/platform/ohos/surface/ohos_native_window.h" +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { +namespace { +TaskRunners MakeTaskRunners(const std::string& threadLabel) +{ + fml::MessageLoop::EnsureInitializedForCurrentThread(); + auto& loop = fml::MessageLoop::GetCurrent(); + return { + threadLabel, + loop.GetTaskRunner(), // platform + loop.GetTaskRunner(), // raster + loop.GetTaskRunner(), // ui + loop.GetTaskRunner() // io + }; +} + +std::unique_ptr CreateOhosContext() +{ + auto environment = fml::MakeRefCounted(); + std::string threadLabel = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + TaskRunners taskRunners = MakeTaskRunners(threadLabel); + return std::make_unique(OHOSRenderingAPI::kOpenGLES, environment, taskRunners, 0); +} +} // namespace +TEST(OHOSContextGlSkiaTest, CreateOnscreenSurface) +{ + std::unique_ptr context = CreateOhosContext(); + EXPECT_TRUE(context.get() != nullptr); + + auto window = fml::MakeRefCounted(nullptr); + std::unique_ptr surface = context->CreateOnscreenSurface(window); + EXPECT_TRUE(surface.get() != nullptr); +} + +TEST(OHOSContextGlSkiaTest, CreateOffscreenSurface) +{ + std::unique_ptr context = CreateOhosContext(); + EXPECT_TRUE(context.get() != nullptr); + + std::unique_ptr surface = context->CreateOffscreenSurface(); + EXPECT_TRUE(surface->IsValid()); +} + +TEST(OHOSContextGlSkiaTest, CreatePbufferSurface) +{ + std::unique_ptr context = CreateOhosContext(); + EXPECT_TRUE(context.get() != nullptr); + + std::unique_ptr surface = context->CreatePbufferSurface(); + EXPECT_TRUE(surface->IsValid()); +} + +TEST(OHOSContextGlSkiaTest, Environment) +{ + std::unique_ptr context = CreateOhosContext(); + EXPECT_TRUE(context.get() != nullptr); + + fml::RefPtr environment = context->Environment(); + EXPECT_TRUE(environment.get() != nullptr); +} + +TEST(OHOSContextGlSkiaTest, ClearCurrent) +{ + std::unique_ptr context = CreateOhosContext(); + EXPECT_TRUE(context.get() != nullptr); + EXPECT_TRUE(context->ClearCurrent()); +} + +TEST(OHOSContextGlSkiaTest, CreateNewContext) +{ + std::unique_ptr context = CreateOhosContext(); + EXPECT_TRUE(context.get() != nullptr); + + EGLContext newContext = context->CreateNewContext(); + EXPECT_TRUE(newContext != EGL_NO_CONTEXT); +} +} +} + diff --git a/shell/platform/ohos/testing/ohos_display_uinttests.cpp b/shell/platform/ohos/testing/ohos_display_uinttests.cpp new file mode 100644 index 0000000000..78bd056765 --- /dev/null +++ b/shell/platform/ohos/testing/ohos_display_uinttests.cpp @@ -0,0 +1,34 @@ +/* + * 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 +#include +#include + +#include "flutter/shell/platform/ohos/ohos_display.h" +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { + +const double DEFAULT_FPS = 60; +TEST(OHOSDisplayTest, GetRefreshRate) +{ + std::shared_ptr display = std::make_shared(nullptr); + EXPECT_TRUE(display.get() != nullptr); + EXPECT_EQ(display->GetRefreshRate(), DEFAULT_FPS); +} +} +} \ No newline at end of file diff --git a/shell/platform/ohos/testing/ohos_egl_surface_unittests.cpp b/shell/platform/ohos/testing/ohos_egl_surface_unittests.cpp new file mode 100644 index 0000000000..62980266b0 --- /dev/null +++ b/shell/platform/ohos/testing/ohos_egl_surface_unittests.cpp @@ -0,0 +1,116 @@ +/* + * 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 +#include +#include + +#include "flutter/common/task_runners.h" +#include "flutter/shell/common/thread_host.h" +#include "flutter/shell/platform/ohos/ohos_context_gl_skia.h" +#include "flutter/shell/platform/ohos/ohos_egl_surface.h" +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { +namespace { +TaskRunners MakeTaskRunners(const std::string& threadLabel) +{ + fml::MessageLoop::EnsureInitializedForCurrentThread(); + auto& loop = fml::MessageLoop::GetCurrent(); + return { + threadLabel, + loop.GetTaskRunner(), // platform + loop.GetTaskRunner(), // raster + loop.GetTaskRunner(), // ui + loop.GetTaskRunner() // io + }; +} + +std::unique_ptr CreateOhosContext() +{ + fml::RefPtr environment = fml::MakeRefCounted(); + std::string threadLabel = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + TaskRunners taskRunners = MakeTaskRunners(threadLabel); + return std::make_unique(OHOSRenderingAPI::kOpenGLES, environment, taskRunners, 0); +} +} // namespace + +TEST(OHOSEGLSurfaceTest, MakeCurrent) +{ + std::unique_ptr context = CreateOhosContext(); + EXPECT_TRUE(context.get() != nullptr); + + std::unique_ptr surface = context->CreateOffscreenSurface(); + EXPECT_TRUE(surface->IsValid()); + + OhosEGLSurfaceMakeCurrentStatus status = surface->MakeCurrent(); + EXPECT_EQ(status, OhosEGLSurfaceMakeCurrentStatus::kSuccessMadeCurrent); +} + +TEST(OHOSEGLSurfaceTest, SupportsPartialRepaint) +{ + std::unique_ptr context = CreateOhosContext(); + EXPECT_TRUE(context.get() != nullptr); + + std::unique_ptr surface = context->CreateOffscreenSurface(); + EXPECT_TRUE(surface->IsValid()); + + bool res = surface->SupportsPartialRepaint(); + EXPECT_EQ(res, false); +} + +TEST(OHOSEGLSurfaceTest, InitialDamage) +{ + std::unique_ptr context = CreateOhosContext(); + EXPECT_TRUE(context.get() != nullptr); + + std::unique_ptr surface = context->CreateOffscreenSurface(); + EXPECT_TRUE(surface->IsValid()); + + std::optional rect = surface->InitialDamage(); + EXPECT_EQ(rect.has_value(), false); +} + +TEST(OHOSEGLSurfaceTest, SetDamageRegion) +{ + std::unique_ptr context = CreateOhosContext(); + EXPECT_TRUE(context.get() != nullptr); + + std::unique_ptr surface = context->CreateOffscreenSurface(); + EXPECT_TRUE(surface->IsValid()); + + std::optional rect(SkIRect::MakeEmpty()); + surface->SetDamageRegion(rect); + EXPECT_EQ(rect.has_value(), true); + SkISize size = surface->GetSize(); + EXPECT_TRUE(size.width() != 0); + EXPECT_TRUE(size.height() != 0); +} + +TEST(OHOSEGLSurfaceTest, SetPresentationTime) +{ + std::unique_ptr context = CreateOhosContext(); + EXPECT_TRUE(context.get() != nullptr); + + std::unique_ptr surface = context->CreateOffscreenSurface(); + EXPECT_TRUE(surface->IsValid()); + + fml::TimePoint timePoint = fml::TimePoint::CurrentWallTime(); + bool res = surface->SetPresentationTime(timePoint); + EXPECT_EQ(res, false); +} +} +} \ No newline at end of file diff --git a/shell/platform/ohos/testing/ohos_environment_gl_unittests.cpp b/shell/platform/ohos/testing/ohos_environment_gl_unittests.cpp new file mode 100644 index 0000000000..096ae8bfe5 --- /dev/null +++ b/shell/platform/ohos/testing/ohos_environment_gl_unittests.cpp @@ -0,0 +1,32 @@ +/* + * 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 +#include +#include + +#include "flutter/shell/platform/ohos/ohos_environment_gl.h" +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { + +TEST(OHOSEnvironmentGLTest, Create) +{ + fml::RefPtr environment = fml::MakeRefCounted(); + EXPECT_TRUE(environment->IsValid()); +} +} +} \ No newline at end of file diff --git a/shell/platform/ohos/testing/ohos_external_texture_gl_unittests.cpp b/shell/platform/ohos/testing/ohos_external_texture_gl_unittests.cpp new file mode 100644 index 0000000000..5e1cda2737 --- /dev/null +++ b/shell/platform/ohos/testing/ohos_external_texture_gl_unittests.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 +#include +#include + +#include "flutter/shell/platform/ohos/ohos_external_texture_gl.h" +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { + +namespace { +TaskRunners MakeTaskRunners(const std::string& threadLabel) +{ + fml::MessageLoop::EnsureInitializedForCurrentThread(); + auto& loop = fml::MessageLoop::GetCurrent(); + return { + threadLabel, + loop.GetTaskRunner(), // platform + loop.GetTaskRunner(), // raster + loop.GetTaskRunner(), // ui + loop.GetTaskRunner() // io + }; +} + +std::shared_ptr CreateOhosContext() +{ + fml::RefPtr environment = fml::MakeRefCounted(); + std::string threadLabel = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + TaskRunners taskRunners = MakeTaskRunners(threadLabel); + return std::make_shared(OHOSRenderingAPI::kOpenGLES, environment, taskRunners, 0); +} +} // namespace + +TEST(OHOSExternalTextureGLTest, OnTextureUnregistered) +{ + std::shared_ptr context = CreateOhosContext(); + EXPECT_TRUE(context.get() != nullptr); + std::shared_ptr surfaceSkia = std::make_shared(context); + std::shared_ptr extTexture = std::make_shared(0, surfaceSkia); + + extTexture->OnTextureUnregistered(); + EXPECT_TRUE(extTexture->first_update_ == false); +} +} +} \ No newline at end of file -- Gitee From c26b8d771b019b957d7dc6165ffa616bbaf17b90 Mon Sep 17 00:00:00 2001 From: hezhengyi Date: Wed, 30 Oct 2024 11:08:32 +0800 Subject: [PATCH 084/151] =?UTF-8?q?XComponent=E8=AE=BE=E7=BD=AE=E4=B8=BA?= =?UTF-8?q?=E5=B7=A6=E4=B8=8A=E8=A7=92=E5=AF=B9=E9=BD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hezhengyi --- .../flutter/src/main/ets/embedding/ohos/FlutterPage.ets | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets index de520a54ea..15af51a2dd 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets @@ -61,6 +61,7 @@ export struct FlutterPage { Log.d(TAG, "XComponent onDestroy "); this.flutterView?.onSurfaceDestroyed() }) + .renderFit(RenderFit.TOP_LEFT) .backgroundColor(Color.Transparent) if (this.showSplashScreen) { @@ -114,6 +115,7 @@ export struct FlutterPage { Log.d(TAG, "XComponent onDestroy "); this.flutterView?.onSurfaceDestroyed() }) + .renderFit(RenderFit.TOP_LEFT) .backgroundColor(Color.Transparent) if (this.showSplashScreen) { -- Gitee From 958a7e09c15913eaefd4ba685a22193e565a024b Mon Sep 17 00:00:00 2001 From: chaoxizhang Date: Fri, 25 Oct 2024 12:00:03 +0800 Subject: [PATCH 085/151] Fix har unstripped package config Signed-off-by: chaoxizhang --- .../ohos/flutter_embedding/flutter/build-profile.json5 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/shell/platform/ohos/flutter_embedding/flutter/build-profile.json5 b/shell/platform/ohos/flutter_embedding/flutter/build-profile.json5 index 489faa5430..b93937f294 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/build-profile.json5 +++ b/shell/platform/ohos/flutter_embedding/flutter/build-profile.json5 @@ -20,6 +20,12 @@ "workers": [ "./src/main/ets/embedding/engine/workers/PlatformChannelWorker.ets" ] + }, + "nativeLib": { + "debugSymbol": { + "strip": false, + "exclude": [] + } } }, "buildOptionSet": [ -- Gitee From 50009b16dfc22634187ae0d4441b939a4815ee65 Mon Sep 17 00:00:00 2001 From: changleipeng Date: Thu, 24 Oct 2024 14:24:07 +0800 Subject: [PATCH 086/151] fml UT Signed-off-by: changleipeng --- BUILD.gn | 20 ++++- attachment/repos/angle.patch | 91 +++++++++++++++++--- attachment/repos/swiftshader.patch | 98 ++++++++++++++++++++++ attachment/scripts/config.json | 6 ++ attachment/scripts/config_pre.json | 6 ++ fml/BUILD.gn | 3 + fml/platform/ohos/napi_util_unittests.cpp | 62 ++++++++++++++ fml/platform/ohos/paths_ohos_unittests.cpp | 29 +++++++ fml/platform/ohos/timerfd_unittests.cpp | 72 ++++++++++++++++ shell/common/BUILD.gn | 19 +++-- shell/config.gni | 2 +- shell/gpu/gpu_surface_vulkan.cc | 4 + shell/platform/embedder/BUILD.gn | 2 +- testing/testing.gni | 6 +- vulkan/vulkan_window.cc | 4 + 15 files changed, 402 insertions(+), 22 deletions(-) create mode 100644 attachment/repos/swiftshader.patch create mode 100644 fml/platform/ohos/napi_util_unittests.cpp create mode 100644 fml/platform/ohos/paths_ohos_unittests.cpp create mode 100644 fml/platform/ohos/timerfd_unittests.cpp diff --git a/BUILD.gn b/BUILD.gn index 7a102d594b..a07cd86e2b 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -152,9 +152,6 @@ group("unittests") { "//flutter/runtime:no_dart_plugin_registrant_unittests", "//flutter/runtime:runtime_unittests", "//flutter/shell/common:shell_unittests", - "//flutter/shell/platform/embedder:embedder_a11y_unittests", - "//flutter/shell/platform/embedder:embedder_proctable_unittests", - "//flutter/shell/platform/embedder:embedder_unittests", "//flutter/testing:testing_unittests", "//flutter/testing/dart", "//flutter/testing/smoke_test_failure", @@ -162,6 +159,21 @@ group("unittests") { "//flutter/third_party/txt:txt_unittests", ] + # ohos does not support vulkan + if (!is_ohos) { + public_deps += [ + "//flutter/shell/platform/embedder:embedder_a11y_unittests", + "//flutter/shell/platform/embedder:embedder_proctable_unittests", + "//flutter/shell/platform/embedder:embedder_unittests", + ] + } + + if (is_ohos) { + public_deps += [ + "//flutter/fml/:fml_unittests", + ] + } + # The accessibility library only supports Mac and Windows at the moment. if (is_mac || is_win) { public_deps += @@ -181,7 +193,7 @@ group("unittests") { [ "//flutter/shell/platform/darwin:flutter_channels_unittests" ] } - if (!is_win && !is_fuchsia) { + if (!is_win && !is_fuchsia && !is_ohos) { public_deps += [ "//flutter/shell/platform/android/external_view_embedder:android_external_view_embedder_unittests", "//flutter/shell/platform/android/jni:jni_unittests", diff --git a/attachment/repos/angle.patch b/attachment/repos/angle.patch index e4a0952dd4..837d591f23 100644 --- a/attachment/repos/angle.patch +++ b/attachment/repos/angle.patch @@ -1,8 +1,19 @@ diff --git a/BUILD.gn b/BUILD.gn -index efaf09033..73af49870 100644 +index efaf090339..cc0398c0e4 100644 --- a/BUILD.gn +++ b/BUILD.gn -@@ -83,7 +83,7 @@ if (angle_build_all) { +@@ -11,7 +11,9 @@ if (angle_use_wayland) { + import("//build_overrides/wayland.gni") + } + if (angle_has_build) { +- import("//build/config/linux/pkg_config.gni") ++ if (!is_ohos) { ++ import("//build/config/linux/pkg_config.gni") ++ } + import("//build/config/sanitizers/sanitizers.gni") + import("//build/config/ui.gni") + import("//testing/libfuzzer/fuzzer_test.gni") +@@ -83,7 +85,7 @@ if (angle_build_all) { ":translator_fuzzer", ":xxhash_fuzzer", "$angle_root/samples:angle_samples", @@ -11,18 +22,43 @@ index efaf09033..73af49870 100644 ] if (angle_enable_cl) { deps += [ "$angle_root/src/libOpenCL:angle_cl" ] -@@ -486,7 +486,8 @@ angle_static_library("angle_image_util") { - sources = libangle_image_util_sources +@@ -141,7 +143,7 @@ config("internal_config") { + if (angle_is_winuwp) { + defines += [ "ANGLE_IS_WINUWP" ] + } +- } else if (is_linux || is_chromeos) { ++ } else if (is_linux || is_chromeos || is_ohos) { + defines += [ "ANGLE_IS_LINUX" ] + } + +@@ -443,7 +445,7 @@ angle_static_library("angle_common") { + all_dependent_configs = [ ":angle_disable_pool_alloc" ] + } + +- if (is_linux || is_chromeos) { ++ if (is_linux || is_chromeos || is_ohos) { + libs = [ "dl" ] + } + +@@ -487,6 +489,7 @@ angle_static_library("angle_image_util") { public_configs += [ ":angle_image_util_config" ] public_deps = [ ":angle_image_util_headers" ] -- -+ + + angle_has_astc_encoder = false if (angle_has_astc_encoder) { public_deps += [ "third_party/astc-encoder:astcenc" ] include_dirs = [ "third_party/astc-encoder/src/Source/" ] +@@ -561,7 +564,7 @@ angle_static_library("angle_gpu_info_util") { + libs += [ "dxgi.lib" ] + } + +- if (is_linux || is_chromeos) { ++ if (is_linux || is_chromeos || is_ohos) { + sources += libangle_gpu_info_util_linux_sources + + if (angle_use_x11 && angle_has_build) { diff --git a/gni/angle.gni b/gni/angle.gni -index b8086660a..d82d056d6 100644 +index b8086660a1..d82d056d65 100644 --- a/gni/angle.gni +++ b/gni/angle.gni @@ -60,8 +60,7 @@ if (angle_has_build) { @@ -65,7 +101,7 @@ index b8086660a..d82d056d6 100644 angle_build_vulkan_system_info = angle_has_build && !angle_is_winuwp diff --git a/include/EGL/eglplatform.h b/include/EGL/eglplatform.h -index 9ebaf00a9..fe111d115 100644 +index 9ebaf00a9b..fe111d115d 100644 --- a/include/EGL/eglplatform.h +++ b/include/EGL/eglplatform.h @@ -117,13 +117,19 @@ typedef khronos_uintptr_t EGLNativeWindowType; @@ -95,7 +131,7 @@ index 9ebaf00a9..fe111d115 100644 #elif defined(__APPLE__) diff --git a/src/common/angle_version.h b/src/common/angle_version.h -index d9d7e8929..a97e3844b 100644 +index d9d7e8929d..a97e3844ba 100644 --- a/src/common/angle_version.h +++ b/src/common/angle_version.h @@ -14,8 +14,12 @@ @@ -112,7 +148,7 @@ index d9d7e8929..a97e3844b 100644 #define ANGLE_STRINGIFY(x) #x #define ANGLE_MACRO_STRINGIFY(x) ANGLE_STRINGIFY(x) diff --git a/src/compiler/translator/BuildSPIRV.h b/src/compiler/translator/BuildSPIRV.h -index d67bd812b..00d22d025 100644 +index d67bd812ba..00d22d025d 100644 --- a/src/compiler/translator/BuildSPIRV.h +++ b/src/compiler/translator/BuildSPIRV.h @@ -110,6 +110,8 @@ struct SpirvType @@ -124,3 +160,38 @@ index d67bd812b..00d22d025 100644 struct SpirvIdAndIdList { spirv::IdRef id; +diff --git a/src/libANGLE/renderer/gl/BUILD.gn b/src/libANGLE/renderer/gl/BUILD.gn +index c675c26074..6cba114ef8 100644 +--- a/src/libANGLE/renderer/gl/BUILD.gn ++++ b/src/libANGLE/renderer/gl/BUILD.gn +@@ -125,7 +125,7 @@ if (angle_use_x11) { + ] + } + +-if (is_android || is_linux || is_chromeos) { ++if (is_android || is_linux || is_chromeos || is_ohos) { + _gl_backend_sources += [ + "egl/ContextEGL.cpp", + "egl/ContextEGL.h", +@@ -264,7 +264,7 @@ angle_source_set("angle_gl_backend") { + "Xext", + ] + } +- if (is_android || is_linux || is_chromeos) { ++ if (is_android || is_linux || is_chromeos || is_ohos) { + deps += [ "$angle_root/src/common/linux:angle_dma_buf" ] + } + if (is_apple) { +diff --git a/src/libGLESv2.gni b/src/libGLESv2.gni +index 723d7f99f2..dab8b887ce 100644 +--- a/src/libGLESv2.gni ++++ b/src/libGLESv2.gni +@@ -87,7 +87,7 @@ xxhash_sources = [ + "src/common/third_party/xxhash/xxhash.h", + ] + +-if (is_linux || is_chromeos || is_android || is_fuchsia) { ++if (is_linux || is_chromeos || is_android || is_fuchsia || is_ohos) { + libangle_common_sources += [ + "src/common/system_utils_linux.cpp", + "src/common/system_utils_posix.cpp", diff --git a/attachment/repos/swiftshader.patch b/attachment/repos/swiftshader.patch new file mode 100644 index 0000000000..e1606d8da2 --- /dev/null +++ b/attachment/repos/swiftshader.patch @@ -0,0 +1,98 @@ +diff --git a/src/Reactor/BUILD.gn b/src/Reactor/BUILD.gn +index 676f99f1a..36a581f10 100644 +--- a/src/Reactor/BUILD.gn ++++ b/src/Reactor/BUILD.gn +@@ -95,7 +95,7 @@ if (supports_subzero) { + if (is_win) { + include_dirs += + [ "../../third_party/llvm-subzero/build/Windows/include/" ] +- } else if (is_linux || is_chromeos) { ++ } else if (is_linux || is_chromeos || is_ohos) { + include_dirs += [ "../../third_party/llvm-subzero/build/Linux/include/" ] + } else if (is_fuchsia) { + include_dirs += +@@ -328,7 +328,7 @@ if (supports_llvm) { + "$llvm_dir/configs/common/include/", + ] + +- if (is_linux || is_chromeos) { ++ if (is_linux || is_chromeos || is_ohos) { + include_dirs += [ "$llvm_dir/configs/linux/include/" ] + } else if (is_fuchsia) { + include_dirs += [ "$llvm_dir/configs/fuchsia/include/" ] +diff --git a/src/Reactor/reactor.gni b/src/Reactor/reactor.gni +index 04fad6f81..324003e35 100644 +--- a/src/Reactor/reactor.gni ++++ b/src/Reactor/reactor.gni +@@ -14,7 +14,7 @@ declare_args() { + } + + declare_args() { +- supports_llvm = is_linux || is_chromeos || is_fuchsia || is_win || is_android ++ supports_llvm = is_linux || is_chromeos || is_fuchsia || is_win || is_android || is_ohos + # LLVM uses C++17 features which require macOS 10.12, while Chrome's minimum platform for x86 is 10.11. + # Don't build LLVM on Mac, unless we have to. This only happens on ARM64 devices, which launched with 11.0. + # TODO(b/174843857): Remove check for !supports_subzero once Chrome supports macOS 10.12 +diff --git a/src/System/BUILD.gn b/src/System/BUILD.gn +index 6f61d9f76..bed58a57b 100644 +--- a/src/System/BUILD.gn ++++ b/src/System/BUILD.gn +@@ -29,7 +29,7 @@ swiftshader_source_set("System_headers") { + "SwiftConfig.hpp", + "Timer.hpp", + ] +- if (is_linux || is_chromeos || is_android) { ++ if (is_linux || is_chromeos || is_android || is_ohos) { + sources += [ + "Linux/MemFd.hpp", + ] +@@ -48,7 +48,7 @@ swiftshader_source_set("System") { + "SwiftConfig.cpp", + "Timer.cpp", + ] +- if (is_linux || is_chromeos || is_android) { ++ if (is_linux || is_chromeos || is_android || is_ohos) { + sources += [ + "Linux/MemFd.cpp", + ] +diff --git a/third_party/llvm-10.0/BUILD.gn b/third_party/llvm-10.0/BUILD.gn +index 6c40b2c00..6076f2bea 100644 +--- a/third_party/llvm-10.0/BUILD.gn ++++ b/third_party/llvm-10.0/BUILD.gn +@@ -100,7 +100,7 @@ llvm_include_dirs = [ + "configs/common/lib/Transforms/InstCombine/", + ] + +-if (is_linux || is_chromeos) { ++if (is_linux || is_chromeos || is_ohos) { + llvm_include_dirs += [ "configs/linux/include/" ] + } else if (is_fuchsia) { + llvm_include_dirs += [ "configs/fuchsia/include/" ] +diff --git a/third_party/marl/src/thread.cpp b/third_party/marl/src/thread.cpp +index 30897f020..a6c3031c2 100644 +--- a/third_party/marl/src/thread.cpp ++++ b/third_party/marl/src/thread.cpp +@@ -154,14 +154,6 @@ Thread::Affinity Thread::Affinity::all( + auto thread = pthread_self(); + cpu_set_t cpuset; + CPU_ZERO(&cpuset); +- if (pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset) == 0) { +- int count = CPU_COUNT(&cpuset); +- for (int i = 0; i < count; i++) { +- Core core; +- core.pthread.index = static_cast(i); +- affinity.cores.emplace_back(std::move(core)); +- } +- } + #elif defined(__FreeBSD__) + auto thread = pthread_self(); + cpuset_t cpuset; +@@ -385,8 +377,6 @@ class Thread::Impl { + for (size_t i = 0; i < count; i++) { + CPU_SET(affinity[i].pthread.index, &cpuset); + } +- auto thread = pthread_self(); +- pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset); + #elif defined(__FreeBSD__) + cpuset_t cpuset; + CPU_ZERO(&cpuset); \ No newline at end of file diff --git a/attachment/scripts/config.json b/attachment/scripts/config.json index 9092b1a939..0e768859f2 100644 --- a/attachment/scripts/config.json +++ b/attachment/scripts/config.json @@ -70,5 +70,11 @@ "target": "third_party/boringssl", "type": "patch", "file_path": "flutter/attachment/repos/boringssl.patch" + }, + { + "name": "swiftshader", + "target": "./src/third_party/swiftshader", + "type": "patch", + "file_path": "../../flutter/attachment/repos/swiftshader.patch" } ] diff --git a/attachment/scripts/config_pre.json b/attachment/scripts/config_pre.json index 9092b1a939..0e768859f2 100644 --- a/attachment/scripts/config_pre.json +++ b/attachment/scripts/config_pre.json @@ -70,5 +70,11 @@ "target": "third_party/boringssl", "type": "patch", "file_path": "flutter/attachment/repos/boringssl.patch" + }, + { + "name": "swiftshader", + "target": "./src/third_party/swiftshader", + "type": "patch", + "file_path": "../../flutter/attachment/repos/swiftshader.patch" } ] diff --git a/fml/BUILD.gn b/fml/BUILD.gn index 03d286857c..bc70dd0f79 100644 --- a/fml/BUILD.gn +++ b/fml/BUILD.gn @@ -364,6 +364,9 @@ if (enable_unittests) { "time/time_delta_unittest.cc", "time/time_point_unittest.cc", "time/time_unittest.cc", + "platform/ohos/timerfd_unittests.cpp", + "platform/ohos/paths_ohos_unittests.cpp", + "platform/ohos/napi_util_unittests.cpp", ] if (is_mac) { diff --git a/fml/platform/ohos/napi_util_unittests.cpp b/fml/platform/ohos/napi_util_unittests.cpp new file mode 100644 index 0000000000..a5e67eb19f --- /dev/null +++ b/fml/platform/ohos/napi_util_unittests.cpp @@ -0,0 +1,62 @@ +/* + * 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 "flutter/fml/platform/ohos/napi_util.h" +#include "gtest/gtest.h" + +namespace fml { +namespace { +TEST(NapiUtilTest, NapiUtil01) { + napi_env env = nullptr; + napi_value value = nullptr; + EXPECT_EQ(napi::NapiIsNull(env, value), true); +} + +TEST(NapiUtilTest, NapiUtil02) { + napi_env env = nullptr; + napi_value value = nullptr; + std::string str = "test"; + EXPECT_EQ(napi::GetString(env, value, str), napi::ERROR_TYPE); +} + +TEST(NapiUtilTest, NapiUtil03) { + napi_env env = nullptr; + napi_value value = nullptr; + std::vector vectorStr = {}; + EXPECT_NE(napi::GetArrayString(env, value, vectorStr), napi::SUCCESS); +} + +TEST(NapiUtilTest, NapiUtil04) { + napi_env env = nullptr; + napi_value value = nullptr; + void** message = nullptr; + size_t lenth = 0; + EXPECT_NE(napi::GetArrayBuffer(env, value, message, &lenth), napi::SUCCESS); +} + +TEST(NapiUtilTest, NapiUtil05) { + napi_env env = nullptr; + napi_value value = nullptr; + EXPECT_EQ(napi::NapiIsType(env, value, napi_number), false); +} + +TEST(NapiUtilTest, NapiUtil06) { + napi_env env = nullptr; + napi_ref ref_napi_obj = nullptr; + EXPECT_GT(napi::InvokeJsMethod(env, ref_napi_obj, nullptr, 0, nullptr), 0); +} + +} // namespace +} // namespace fml \ No newline at end of file diff --git a/fml/platform/ohos/paths_ohos_unittests.cpp b/fml/platform/ohos/paths_ohos_unittests.cpp new file mode 100644 index 0000000000..2267050aad --- /dev/null +++ b/fml/platform/ohos/paths_ohos_unittests.cpp @@ -0,0 +1,29 @@ +/* + * 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 "flutter/fml/platform/ohos/paths_ohos.h" +#include "gtest/gtest.h" + +namespace fml { +namespace { +TEST(PathsTest, PathsOhosTest01) { + fml::paths::InitializeOhosCachesPath("test"); + fml::UniqueFD resultFD = fml::paths::GetCachesDirectory(); + EXPECT_FALSE(resultFD.is_valid()); +} + + +} // namespace +} // namespace fml \ No newline at end of file diff --git a/fml/platform/ohos/timerfd_unittests.cpp b/fml/platform/ohos/timerfd_unittests.cpp new file mode 100644 index 0000000000..6da8a3f2f7 --- /dev/null +++ b/fml/platform/ohos/timerfd_unittests.cpp @@ -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. + */ +#include +#include +#include +#include +#include "flutter/fml/platform/ohos/timerfd.h" + +#include "gtest/gtest.h" + +using fml::TimePoint; +namespace fml { +namespace { + +class MockFileDescriptor { +public: + MockFileDescriptor() + { + pipe(mFdArray); + } + + ~MockFileDescriptor() + { + close(mFdArray[0]); + close(mFdArray[1]); + } + + int GetReadFd() const { return mFdArray[0]; } + int GetWriteFd() const { return mFdArray[1]; } + + void WriteFireCount(uint64_t count) + { + write(mFdArray[1], &count, sizeof(count)); + } + +private: + int mFdArray[2]; +}; +TEST(TimerfdTest, TimerRearmTest) { + TimePoint timeP; + EXPECT_EQ(TimerRearm(0, timeP), false); +} + +TEST(TimerDrainTest, ReadsFireCountSuccessfully) { + MockFileDescriptor mockFd; + uint64_t expected_count = 1; + mockFd.WriteFireCount(expected_count); + EXPECT_TRUE(TimerDrain(mockFd.GetReadFd())); +} + +TEST(TimerfdTest, TimerFdCreateTest) { + EXPECT_TRUE(timerfd_create(0, 0)); +} + +TEST(TimerfdTest, TimerFdSettimeTest) { + EXPECT_EQ(timerfd_settime(0, 0, nullptr, nullptr), -1); +} + +} // namespace +} // namespace fml \ No newline at end of file diff --git a/shell/common/BUILD.gn b/shell/common/BUILD.gn index 7fa0c1b23a..2f8b67095e 100644 --- a/shell/common/BUILD.gn +++ b/shell/common/BUILD.gn @@ -185,6 +185,10 @@ if (enable_unittests) { "fixtures/shelltest_screenshot.png", "fixtures/hello_loop_2.gif", ] + + if (is_ohos) { + dest = "/data/flutter_unittests/common" + } } shell_host_executable("shell_benchmarks") { @@ -284,16 +288,12 @@ if (enable_unittests) { testonly = true sources = [ - "animator_unittests.cc", "canvas_spy_unittests.cc", "context_options_unittests.cc", "engine_unittests.cc", - "input_events_unittests.cc", - "persistent_cache_unittests.cc", "pipeline_unittests.cc", "rasterizer_unittests.cc", "resource_cache_limit_calculator_unittests.cc", - "shell_unittests.cc", "switches_unittests.cc", "variable_refresh_rate_display_unittests.cc", "vsync_waiter_unittests.cc", @@ -310,6 +310,15 @@ if (enable_unittests) { "//third_party/googletest:gmock", ] + if (!is_ohos) { + sources += [ + "animator_unittests.cc", + "input_events_unittests.cc", + "persistent_cache_unittests.cc", + "shell_unittests.cc", + ] + } + if (is_fuchsia) { sources += [ "shell_fuchsia_unittests.cc" ] @@ -319,7 +328,7 @@ if (enable_unittests) { "$fuchsia_sdk_root/pkg:fidl_cpp", "$fuchsia_sdk_root/pkg:sys_cpp", ] - } else { + } else if (!is_ohos) { # TODO(63837): This test is hard-coded to use a TestGLSurface so it cannot run on fuchsia. sources += [ "shell_io_manager_unittests.cc" ] diff --git a/shell/config.gni b/shell/config.gni index 85dd360cbc..4db04f8b5c 100644 --- a/shell/config.gni +++ b/shell/config.gni @@ -17,6 +17,6 @@ declare_args() { test_enable_metal = shell_enable_metal # The Vulkan unittests are combined with the GL unittests. - test_enable_vulkan = is_fuchsia || shell_enable_gl + test_enable_vulkan = (is_fuchsia || shell_enable_gl) && !is_ohos test_enable_software = shell_enable_software } diff --git a/shell/gpu/gpu_surface_vulkan.cc b/shell/gpu/gpu_surface_vulkan.cc index ba8383c134..7743289f59 100644 --- a/shell/gpu/gpu_surface_vulkan.cc +++ b/shell/gpu/gpu_surface_vulkan.cc @@ -98,6 +98,7 @@ sk_sp GPUSurfaceVulkan::CreateSurfaceFromVulkanImage( const VkImage image, const VkFormat format, const SkISize& size) { +#ifdef SK_VULKAN GrVkImageInfo image_info = { .fImage = image, .fImageTiling = VK_IMAGE_TILING_OPTIMAL, @@ -126,6 +127,9 @@ sk_sp GPUSurfaceVulkan::CreateSurfaceFromVulkanImage( SkColorSpace::MakeSRGB(), // color space &surface_properties // surface properties ); +#else + return nullptr; +#endif // SK_VULKAN } SkColorType GPUSurfaceVulkan::ColorTypeFromFormat(const VkFormat format) { diff --git a/shell/platform/embedder/BUILD.gn b/shell/platform/embedder/BUILD.gn index 56335f45af..055c53ca56 100644 --- a/shell/platform/embedder/BUILD.gn +++ b/shell/platform/embedder/BUILD.gn @@ -217,7 +217,7 @@ test_fixtures("fixtures") { ] } -if (enable_unittests) { +if (enable_unittests && !is_ohos) { source_set("embedder_unittests_library") { testonly = true diff --git a/testing/testing.gni b/testing/testing.gni index 3fadcbbc71..e2016e48fc 100644 --- a/testing/testing.gni +++ b/testing/testing.gni @@ -331,7 +331,11 @@ template("test_fixtures") { copy_fixtures_target_name = "_cf_$target_name" copy_fixtures(copy_fixtures_target_name) { fixtures = invoker.fixtures - dest = dest + if (is_ohos) { + dest = target_gen_dir + } else { + dest = dest + } forward_variables_from(invoker, [ "deps" ]) } test_public_deps += [ ":$copy_fixtures_target_name" ] diff --git a/vulkan/vulkan_window.cc b/vulkan/vulkan_window.cc index a7067fff3f..25608f54af 100644 --- a/vulkan/vulkan_window.cc +++ b/vulkan/vulkan_window.cc @@ -116,6 +116,7 @@ GrDirectContext* VulkanWindow::GetSkiaGrContext() { } bool VulkanWindow::CreateSkiaGrContext() { +#ifdef SK_VULKAN GrVkBackendContext backend_context; if (!CreateSkiaBackendContext(&backend_context)) { @@ -136,6 +137,9 @@ bool VulkanWindow::CreateSkiaGrContext() { skia_gr_context_ = context; return true; +#else + return false; +#endif } bool VulkanWindow::CreateSkiaBackendContext(GrVkBackendContext* context) { -- Gitee From 9443bc48199ae0aded209b3020033deeb20aa172 Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 30 Oct 2024 19:30:54 +0800 Subject: [PATCH 087/151] =?UTF-8?q?fix:=E6=97=A0=E9=9A=9C=E7=A2=8D?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=8C=96=E6=B5=8B=E8=AF=95=E8=81=94=E8=B0=83?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E5=A2=9E=E5=8A=A0setcontent=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E4=BD=BF=E7=94=A8=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos/accessibility/ohos_accessibility_bridge.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 1b2b42df97..d1a2ddd5a6 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -45,12 +45,14 @@ void OhosAccessibilityBridge::OnOhosAccessibilityStateChange( { native_shell_holder_id_ = shellHolderId; auto nativeAccessibilityChannel_ = std::make_shared(); + if (ohosAccessibilityEnabled) { FML_DLOG(INFO) << "OnOhosAccessibilityEnabled()"; nativeAccessibilityChannel_->OnOhosAccessibilityEnabled(native_shell_holder_id_); } else { FML_DLOG(INFO) << "OnOhosAccessibilityEnabled()"; nativeAccessibilityChannel_->OnOhosAccessibilityDisabled(native_shell_holder_id_); + ClearFlutterSemanticsCaches(); } } @@ -656,8 +658,6 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( // 防止溢出屏幕坐标 newTop = realParentTop - rootBottom; newBottom = realParentBottom - rootBottom; - // newTop = static_cast(newTop) % static_cast(rootBottom); - // newBottom = static_cast(newBottom) % static_cast(rootBottom); SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); } else { @@ -737,6 +737,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root"); + OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, "root_content"); return; } @@ -924,7 +925,8 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( text.c_str()); FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetAccessibilityText = " << text; - + //set contents (same as AccessibilityText) + OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, text.c_str()); std::string hint = flutterNode.hint; OH_ArkUI_AccessibilityElementInfoSetHintText(elementInfoFromList, hint.c_str()); -- Gitee From 3d34c3845ea16714ef365ce2ce8c71db8ca4ef82 Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 30 Oct 2024 20:52:01 +0800 Subject: [PATCH 088/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E6=97=A0?= =?UTF-8?q?=E9=9A=9C=E7=A2=8D=E9=80=9A=E9=81=93=E5=86=85=E9=83=A8=E7=B1=BB?= =?UTF-8?q?,=E4=BF=AE=E6=94=B9setcontent=E5=86=85=E5=AE=B9,=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E9=80=9A=E9=81=93=E8=81=8C=E8=B4=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../native_accessibility_channel.cpp | 28 +++++++++++++++---- .../native_accessibility_channel.h | 21 ++++++++++---- .../ohos_accessibility_bridge.cpp | 4 +-- .../accessibility/ohos_accessibility_bridge.h | 3 +- .../ohos/napi/platform_view_ohos_napi.cpp | 4 +-- 5 files changed, 42 insertions(+), 18 deletions(-) diff --git a/shell/platform/ohos/accessibility/native_accessibility_channel.cpp b/shell/platform/ohos/accessibility/native_accessibility_channel.cpp index 4beea68300..1d3e8a7a3a 100644 --- a/shell/platform/ohos/accessibility/native_accessibility_channel.cpp +++ b/shell/platform/ohos/accessibility/native_accessibility_channel.cpp @@ -38,10 +38,6 @@ namespace flutter { { FML_DLOG(INFO) << "NativeAccessibilityChannel -> OnOhosAccessibilityDisabled"; this->SetSemanticsEnabled(shellHolderId, false); - - auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); - ohosAccessibilityBridge->ClearFlutterSemanticsCaches(); - FML_DLOG(INFO) << "OnOhosAccessibilityDisabled -> ClearFlutterSemanticsCaches()"; } /** @@ -50,8 +46,6 @@ namespace flutter { void NativeAccessibilityChannel::SetSemanticsEnabled(int64_t shellHolderId, bool enabled) { - FML_DLOG(INFO) << "SetSemanticsEnabled -> shellHolderId: " - << shellHolderId; auto ohos_shell_holder = reinterpret_cast(shellHolderId); ohos_shell_holder->GetPlatformView()->SetSemanticsEnabled(enabled); @@ -82,6 +76,9 @@ namespace flutter { ohos_shell_holder->GetPlatformView()->PlatformView::DispatchSemanticsAction(id, action, fml::MallocMapping()); } + /** + * 更新flutter无障碍相关语义信息 + */ void NativeAccessibilityChannel::UpdateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) @@ -89,4 +86,23 @@ namespace flutter { auto ohos_a11y_bridge = OhosAccessibilityBridge::GetInstance(); ohos_a11y_bridge->updateSemantics(update, actions); } + + /** + * 设置无障碍消息处理器,通过无障碍通道发送处理dart侧传递的相关信息 + */ + void NativeAccessibilityChannel::SetAccessibilityMessageHandler( + std::shared_ptr handler) + { + this->handler = handler; + } + + /** + * 利用通道内部类AccessibilityMessageHandler处理主动播报事件 + */ + void NativeAccessibilityChannel::AccessibilityMessageHandler::Announce( + std::unique_ptr& message) + { + auto ohos_a11y_bridge = OhosAccessibilityBridge::GetInstance(); + ohos_a11y_bridge->Announce(message); + } } \ No newline at end of file diff --git a/shell/platform/ohos/accessibility/native_accessibility_channel.h b/shell/platform/ohos/accessibility/native_accessibility_channel.h index a2e9053cfc..29d6e895c4 100644 --- a/shell/platform/ohos/accessibility/native_accessibility_channel.h +++ b/shell/platform/ohos/accessibility/native_accessibility_channel.h @@ -14,6 +14,7 @@ */ #ifndef OHOS_NATIVE_ACCESSIBILITY_CHANNEL_H #define OHOS_NATIVE_ACCESSIBILITY_CHANNEL_H +#include #include "flutter/fml/mapping.h" #include "flutter/lib/ui/semantics/semantics_node.h" #include "flutter/lib/ui/semantics/custom_accessibility_action.h" @@ -40,15 +41,23 @@ class NativeAccessibilityChannel { void UpdateSemantics(flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions); -}; + class AccessibilityMessageHandler { + public: + void Announce(std::unique_ptr& message); -class AccessibilityDelegate { - public: - AccessibilityDelegate(); - ~AccessibilityDelegate(); + void OnTap(int32_t nodeId); -}; + void OnLongPress(int32_t nodeId); + void OnTooltip(std::unique_ptr& message); + }; + + void SetAccessibilityMessageHandler( + std::shared_ptr handler); + + private: + std::shared_ptr handler; +}; } #endif \ No newline at end of file diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index d1a2ddd5a6..c6510d8cda 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -377,7 +377,7 @@ bool OhosAccessibilityBridge::IsScrollableWidget( /** * 主动播报特定文本 */ -void OhosAccessibilityBridge::announce(std::unique_ptr& message) +void OhosAccessibilityBridge::Announce(std::unique_ptr& message) { // 创建并设置屏幕朗读事件 ArkUI_AccessibilityEventInfo* announceEventInfo = @@ -737,7 +737,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root"); - OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, "root_content"); + OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, flutterNode.label); return; } diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 34880ea8d6..de11c80125 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -83,9 +83,8 @@ class OhosAccessibilityBridge { flutter::SemanticsAction action, fml::MallocMapping args); - void announce(std::unique_ptr& message); + void Announce(std::unique_ptr& message); - // obtain the flutter semnatics node flutter::SemanticsNode getOrCreateFlutterSemanticsNode(int32_t id); int32_t FindAccessibilityNodeInfosById( diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index e56df51cc5..06a086d5db 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1907,8 +1907,8 @@ napi_value PlatformViewOHOSNapi::nativeAnnounce( napi_get_value_string_utf8(env, args[0], char_array.get(), null_terminated_length, nullptr); LOGD("PlatformViewOHOSNapi::nativeAnnounce message: %{public}s", char_array.get()); - auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); - ohosAccessibilityBridge->announce(char_array); + auto handler = std::make_shared(); + handler->Announce(char_array); return nullptr; } -- Gitee From 1e16e7dfc96836f506fa0458142c19bd81987077 Mon Sep 17 00:00:00 2001 From: hezhengyi Date: Thu, 31 Oct 2024 11:57:55 +0800 Subject: [PATCH 089/151] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E6=8B=96=E5=8A=A8=E6=97=B6=E5=BA=94=E7=94=A8=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E5=8F=98=E5=BD=A2=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hezhengyi --- shell/platform/ohos/ohos_surface_gl_skia.cpp | 23 ++++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/shell/platform/ohos/ohos_surface_gl_skia.cpp b/shell/platform/ohos/ohos_surface_gl_skia.cpp index dcd4a06481..6c8d5ea57e 100755 --- a/shell/platform/ohos/ohos_surface_gl_skia.cpp +++ b/shell/platform/ohos/ohos_surface_gl_skia.cpp @@ -16,10 +16,12 @@ #include "flutter/shell/platform/ohos/ohos_surface_gl_skia.h" #include +#include #include "flutter/fml/logging.h" #include "flutter/fml/memory/ref_ptr.h" #include "flutter/shell/platform/ohos/ohos_egl_surface.h" +#include "flutter/shell/platform/ohos/ohos_logging.h" #include "flutter/shell/platform/ohos/ohos_shell_holder.h" namespace flutter { @@ -89,17 +91,20 @@ bool OhosSurfaceGLSkia::OnScreenSurfaceResize(const SkISize& size) { return true; } - GLContextPtr()->ClearCurrent(); - - // Ensure the destructor is called since it destroys the `EGLSurface` before - // creating a new onscreen surface. - onscreen_surface_ = nullptr; - onscreen_surface_ = GLContextPtr()->CreateOnscreenSurface(native_window_); - if (!onscreen_surface_->IsValid()) { - FML_LOG(ERROR) << "Unable to create EGL window surface on resize."; + int code = SET_BUFFER_GEOMETRY; + int32_t width = size.fWidth; + int32_t height = size.fHeight; + int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(native_window_->handle(), + code, width, height); + if (ret != 0) { + LOGE( + "OhosSurfaceGLSkia::OnScreenSurfaceResize, window resize failed, " + "ret=%{public}d, " + "width:%{public}d, " + "height:%{public}d", + ret, width, height); return false; } - onscreen_surface_->MakeCurrent(); return true; } -- Gitee From a4c84d39823ae318ff31b19ed5465e2fa90b717f Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 1 Nov 2024 16:56:02 +0800 Subject: [PATCH 090/151] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E5=8F=8D?= =?UTF-8?q?=E5=A4=8D=E5=BC=80=E5=85=B3=E5=B1=8F=E5=B9=95=E6=9C=97=E8=AF=BB?= =?UTF-8?q?=EF=BC=8C=E5=AF=BC=E8=87=B4=E7=83=AD=E5=90=AF=E5=8A=A8flutter?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E6=97=A0=E6=B3=95=E8=AF=86=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 38 +++++++++---------- .../accessibility/ohos_accessibility_bridge.h | 12 +++--- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index c6510d8cda..b439c7e258 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -25,15 +25,21 @@ namespace flutter { -OhosAccessibilityBridge OhosAccessibilityBridge::bridgeInstance; +OhosAccessibilityBridge* OhosAccessibilityBridge::bridgeInstance = nullptr; OhosAccessibilityBridge::OhosAccessibilityBridge() {} -OhosAccessibilityBridge::~OhosAccessibilityBridge() {} - OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() { - return &OhosAccessibilityBridge::bridgeInstance; + if(!bridgeInstance) { + bridgeInstance = new OhosAccessibilityBridge(); + } + return bridgeInstance; +} + +void OhosAccessibilityBridge::DestroyInstance() { + delete bridgeInstance; + bridgeInstance = nullptr; } /** @@ -52,7 +58,6 @@ void OhosAccessibilityBridge::OnOhosAccessibilityStateChange( } else { FML_DLOG(INFO) << "OnOhosAccessibilityEnabled()"; nativeAccessibilityChannel_->OnOhosAccessibilityDisabled(native_shell_holder_id_); - ClearFlutterSemanticsCaches(); } } @@ -342,7 +347,6 @@ SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent( nodeEx.childrenInHitTestOrder = std::move(node.childrenInHitTestOrder); nodeEx.customAccessibilityActions = std::move(node.customAccessibilityActions); - return nodeEx; } @@ -630,15 +634,7 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( newRight = realParentRight; newBottom = realParentBottom; } else { - /** - * 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 (初期版本) - * newLeft = (currLeft + _kMTransX) * realScaleFactor; - * newTop = (currTop + _kMTransY) * realScaleFactor; - * newRight = (currLeft + _kMTransX + currRight) * realScaleFactor; - * newBottom = (currTop + _kMTransY + currBottom) * realScaleFactor; - */ // 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 - // (增强版本) newLeft = (currLeft + _kMTransX) * realScaleFactor + realParentLeft; newTop = (currTop + _kMTransY) * realScaleFactor + realParentTop; newRight = @@ -717,12 +713,13 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( false); // 配置child节点信息 + auto flutterChildVec = flutterNode.childrenInTraversalOrder; int32_t childCount = - static_cast(flutterNode.childrenInTraversalOrder.size()); + static_cast(flutterChildVec.size()); int64_t childNodeIds[childCount]; for (int32_t i = 0; i < childCount; i++) { childNodeIds[i] = - static_cast(flutterNode.childrenInTraversalOrder[i]); + static_cast(flutterChildVec[i]); FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> elementid=0 childCount=" << childCount << " childNodeIds=" << childNodeIds[i]; @@ -737,7 +734,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root"); - OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, flutterNode.label); + OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, flutterNode.label.c_str()); return; } @@ -932,12 +929,15 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( hint.c_str()); // set chidren elementinfo ids + auto flutterChildVec = flutterNode.childrenInTraversalOrder; + //按照升序排列孩子数组id + std::sort(flutterChildVec.begin(), flutterChildVec.end()); int32_t childCount = - static_cast(flutterNode.childrenInTraversalOrder.size()); + static_cast(flutterChildVec.size()); int64_t childNodeIds[childCount]; for (int32_t i = 0; i < childCount; i++) { childNodeIds[i] = - static_cast(flutterNode.childrenInTraversalOrder[i]); + static_cast(flutterChildVec[i]); FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> elementid=" << elementId << " childCount=" << childCount << " childNodeIds=" << childNodeIds[i]; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index de11c80125..e9e171c53c 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -47,7 +47,6 @@ struct AbsoluteRect { struct SemanticsNodeExtent : flutter::SemanticsNode { int32_t parentId = -1; AbsoluteRect abRect = AbsoluteRect::MakeEmpty(); - int32_t previousFlags; int32_t previousActions; int32_t previousTextSelectionBase; @@ -61,10 +60,10 @@ struct SemanticsNodeExtent : flutter::SemanticsNode { class OhosAccessibilityBridge { public: - OhosAccessibilityBridge(); - ~OhosAccessibilityBridge(); - static OhosAccessibilityBridge* GetInstance(); + static void DestroyInstance(); + OhosAccessibilityBridge(const OhosAccessibilityBridge&) = delete; + OhosAccessibilityBridge& operator=(const OhosAccessibilityBridge&) = delete; bool IS_FLUTTER_NAVIGATE = false; int64_t native_shell_holder_id_; @@ -143,7 +142,8 @@ class OhosAccessibilityBridge { void ClearFlutterSemanticsCaches(); private: - static OhosAccessibilityBridge bridgeInstance; + OhosAccessibilityBridge(); + static OhosAccessibilityBridge* bridgeInstance; std::shared_ptr nativeAccessibilityChannel_; static const int32_t ROOT_NODE_ID = 0; @@ -155,7 +155,7 @@ class OhosAccessibilityBridge { flutter::SemanticsNode accessibilityFocusedNode; std::vector> parentChildIdVec; - std::unordered_map flutterSemanticsTree_; + std::map flutterSemanticsTree_; std::unordered_map< int32_t, std::pair, std::pair>> -- Gitee From cfd4d9ce40ef1cebd5947cc91b78af6aa7cc094c Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 1 Nov 2024 18:45:53 +0800 Subject: [PATCH 091/151] =?UTF-8?q?fix:=E5=87=8F=E5=B0=91=E9=9D=9E?= =?UTF-8?q?=E5=B1=8F=E5=B9=95=E6=98=BE=E7=A4=BA=E5=8C=BA=E5=9F=9F=E7=9A=84?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E5=88=9B=E5=BB=BA=E9=81=8D=E5=8E=86=E5=BC=80?= =?UTF-8?q?=E9=94=80,=E5=A4=A7=E5=B9=85=E5=BA=A6=E6=8F=90=E5=8D=87?= =?UTF-8?q?=E5=B1=8F=E5=B9=95=E6=9C=97=E8=AF=BB=E6=BB=91=E5=8A=A8=E6=B5=81?= =?UTF-8?q?=E7=95=85=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos/accessibility/ohos_accessibility_bridge.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index b439c7e258..00fc3acd23 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -177,12 +177,6 @@ void OhosAccessibilityBridge::updateSemantics( continue; } - // 判断flutter节点是否获焦 - if (IsNodeFocusable(node)) { - FML_DLOG(INFO) << "UpdateSemantics -> flutterNode is focusable, node.id=" - << node.id; - } - // 获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 int32_t childNodeCount = node.childrenInTraversalOrder.size(); for (int32_t i = 0; i < childNodeCount; i++) { @@ -1180,6 +1174,9 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( } auto flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); + if(!IsNodeVisible(flutterNode)) { + return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; + } if (mode == ArkUI_AccessibilitySearchMode:: ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { @@ -1954,6 +1951,8 @@ void OhosAccessibilityBridge::GetSemanticsFlagsDebugInfo( flutter::SemanticsNode node) { FML_DLOG(INFO) << "----------------SemanticsFlags-------------------------"; + FML_DLOG(INFO) << "node.id=" << node.id; + FML_DLOG(INFO) << "node.label=" << node.label; FML_DLOG(INFO) << "kHasCheckedState: " << node.HasFlag(FLAGS_::kHasCheckedState); FML_DLOG(INFO) << "kIsChecked:" << node.HasFlag(FLAGS_::kIsChecked); -- Gitee From bf6c83cd7488ba84e9c1717cb83a89c5de76b30e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BA=A6=E7=A9=97?= Date: Fri, 1 Nov 2024 14:19:55 +0800 Subject: [PATCH 092/151] =?UTF-8?q?shell/platform/ohos=20=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95=E8=A1=A5=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 麦穗 --- OAT.xml | 4 + .../flutter_embedding/application/.gitignore | 6 + .../application/build-profile.json5 | 43 +++ .../application/hvigorfile.ts | 20 ++ .../application/obfuscation-rules.txt | 23 ++ .../application/oh-package.json5 | 28 ++ .../applicationability/ApplicationAbility.ets | 55 +++ .../ApplicationBackupAbility.ets | 26 ++ .../application/src/main/ets/pages/Index.ets | 34 ++ .../application/src/main/module.json5 | 52 +++ .../main/resources/base/element/color.json | 8 + .../main/resources/base/element/string.json | 16 + .../main/resources/base/media/background.png | Bin 0 -> 57364 bytes .../main/resources/base/media/foreground.png | Bin 0 -> 12430 bytes .../resources/base/media/layered_image.json | 7 + .../main/resources/base/media/startIcon.png | Bin 0 -> 20093 bytes .../resources/base/profile/backup_config.json | 3 + .../resources/base/profile/main_pages.json | 5 + .../main/resources/en_US/element/string.json | 16 + .../main/resources/zh_CN/element/string.json | 16 + .../application/src/mock/mock-config.json5 | 17 + .../ets/test/FlutterInjector.test.ets | 31 ++ .../src/ohosTest/ets/test/List.test.ets | 153 +++++++++ .../engine/FlutterEngineCacheTest.test.ets | 47 +++ ...utterEngineConnectionRegistryTest.test.ets | 68 ++++ .../FlutterEngineGroupCacheTest.test.ets | 48 +++ .../engine/FlutterEngineGroupTest.test.ets | 53 +++ .../engine/FlutterEngineTest.test.ets | 263 +++++++++++++++ .../embedding/engine/FlutterNapiTest.test.ets | 182 ++++++++++ .../engine/FlutterOverlaySurfaceTest.test.ets | 35 ++ .../engine/FlutterShellArgsTest.test.ets | 62 ++++ .../engine/dart/DartExecutorTest.test.ets | 70 ++++ .../engine/dart/DartMessengerTest.test.ets | 47 +++ .../loader/ApplicationInfoTest.test.ets | 28 ++ .../FlutterApplicationInfoTest.test.ets | 26 ++ .../engine/loader/FlutterLoaderTest.test.ets | 52 +++ .../FlutterMutatorViewTest.test.ets | 27 ++ .../FlutterMutatorsStackTest.test.ets | 90 +++++ .../renderer/FlutterRendererTest.test.ets | 58 ++++ .../systemchannels/LifecycleChannel.test.ets | 71 ++++ .../systemchannels/PlatformChannel.test.ets | 102 ++++++ .../RestorationChannel.test.ets | 71 ++++ .../systemchannels/SettingsChannel.test.ets | 38 +++ .../systemchannels/TextInputChannel.test.ets | 38 +++ ...lutterAbilityAndEntryDelegateTest.test.ets | 78 +++++ .../ohos/FlutterAbilityTest.test.ets | 158 +++++++++ .../embedding/ohos/FlutterEntryTest.test.ets | 181 ++++++++++ .../ohos/FlutterManagerTest.test.ets | 79 +++++ .../test/embedding/ohos/SettingTest.test.ets | 38 +++ .../ohos/TouchEventProcessorTest.test.ets | 41 +++ .../ohos/TouchEventTrackerTest.test.ets | 51 +++ ...ositoryCallbackAdapterWrapperTest.test.ets | 29 ++ .../plugin/common/BinaryCodecTest.test.ets | 37 ++ .../common/BinaryMessengerTest.test.ets | 51 +++ .../plugin/common/FlutterException.test.ets | 58 ++++ .../plugin/common/JSONMessageCodec.test.ets | 29 ++ .../plugin/common/JSONMethodCodec.test.ets | 57 ++++ .../test/plugin/common/MethodCall.test.ets | 34 ++ .../common/SendableBinaryCodec.test.ets | 37 ++ .../common/SendableJSONMessageCodec.test.ets | 29 ++ .../common/SendableJSONMethodCodec.test.ets | 41 +++ .../SendableStandardMessageCodec.test.ets | 88 +++++ .../SendableStandardMethodCodec.test.ets | 35 ++ .../common/SendableStringCodec.test.ets | 43 +++ .../common/StandardMessageCodec.test.ets | 92 +++++ .../common/StandardMethodCodec.test.ets | 32 ++ .../test/plugin/common/StringCodec.test.ets | 38 +++ .../editing/ListenableEditingState.test.ets | 48 +++ .../plugin/editing/TextEditingDelta.test.ets | 33 ++ .../plugin/editing/TextInputPlugin.test.ets | 46 +++ .../localization/LocalizationPlugin.test.ets | 55 +++ .../AccessibilityEventsDelegate.test.ets | 36 ++ .../platform/PlatformOverlayView.test.ets | 32 ++ .../plugin/platform/PlatformView.test.ets | 37 ++ .../PlatformViewRegistryImplTest.test.ets | 36 ++ .../platform/PlatformViewWrapperTest.test.ets | 41 +++ .../PlatformViewsControllerTest.test.ets | 50 +++ .../platform/RawPointerCoordTest.test.ets | 44 +++ .../platform/RootDvModelManagerTest.test.ets | 36 ++ .../test/plugin/util/ByteBufferTest.test.ets | 317 ++++++++++++++++++ .../ets/test/plugin/util/Log.test.ets | 25 ++ .../plugin/util/MessageChannelUtils.test.ets | 25 ++ .../ets/test/plugin/util/PathUtils.test.ets | 32 ++ .../ets/test/plugin/util/StringUtils.test.ets | 30 ++ .../ets/test/plugin/util/ToolUtils.test.ets | 26 ++ .../test/plugin/util/TraceSection.test.ets | 34 ++ .../view/DynamicView/dynamicViewJson.test.ets | 30 ++ .../test/view/FlutterRunArguments.test.ets | 28 ++ .../application/src/ohosTest/module.json5 | 28 ++ .../application/src/test/List.test.ets | 19 ++ .../application/src/test/LocalUnit.test.ets | 47 +++ .../flutter_embedding/build-profile.json5 | 14 +- .../main/ets/embedding/engine/FlutterNapi.ets | 2 +- .../ohos/flutter_embedding/oh-package.json5 | 2 +- 94 files changed, 4545 insertions(+), 3 deletions(-) create mode 100644 shell/platform/ohos/flutter_embedding/application/.gitignore create mode 100644 shell/platform/ohos/flutter_embedding/application/build-profile.json5 create mode 100644 shell/platform/ohos/flutter_embedding/application/hvigorfile.ts create mode 100644 shell/platform/ohos/flutter_embedding/application/obfuscation-rules.txt create mode 100644 shell/platform/ohos/flutter_embedding/application/oh-package.json5 create mode 100644 shell/platform/ohos/flutter_embedding/application/src/main/ets/applicationability/ApplicationAbility.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/main/ets/applicationbackupability/ApplicationBackupAbility.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/main/ets/pages/Index.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/main/module.json5 create mode 100644 shell/platform/ohos/flutter_embedding/application/src/main/resources/base/element/color.json create mode 100644 shell/platform/ohos/flutter_embedding/application/src/main/resources/base/element/string.json create mode 100644 shell/platform/ohos/flutter_embedding/application/src/main/resources/base/media/background.png create mode 100644 shell/platform/ohos/flutter_embedding/application/src/main/resources/base/media/foreground.png create mode 100644 shell/platform/ohos/flutter_embedding/application/src/main/resources/base/media/layered_image.json create mode 100644 shell/platform/ohos/flutter_embedding/application/src/main/resources/base/media/startIcon.png create mode 100644 shell/platform/ohos/flutter_embedding/application/src/main/resources/base/profile/backup_config.json create mode 100644 shell/platform/ohos/flutter_embedding/application/src/main/resources/base/profile/main_pages.json create mode 100644 shell/platform/ohos/flutter_embedding/application/src/main/resources/en_US/element/string.json create mode 100644 shell/platform/ohos/flutter_embedding/application/src/main/resources/zh_CN/element/string.json create mode 100644 shell/platform/ohos/flutter_embedding/application/src/mock/mock-config.json5 create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/FlutterInjector.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/List.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineCacheTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineConnectionRegistryTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineGroupCacheTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineGroupTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterNapiTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterOverlaySurfaceTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterShellArgsTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/dart/DartExecutorTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/dart/DartMessengerTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/loader/ApplicationInfoTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/loader/FlutterApplicationInfoTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/loader/FlutterLoaderTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/mutatorsstack/FlutterMutatorViewTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/mutatorsstack/FlutterMutatorsStackTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/renderer/FlutterRendererTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/LifecycleChannel.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/PlatformChannel.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/RestorationChannel.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/SettingsChannel.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/TextInputChannel.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterAbilityAndEntryDelegateTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterAbilityTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterEntryTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterManagerTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/SettingTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/TouchEventProcessorTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/TouchEventTrackerTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/WindowInfoRepositoryCallbackAdapterWrapperTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/BinaryCodecTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/BinaryMessengerTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/FlutterException.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/JSONMessageCodec.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/JSONMethodCodec.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/MethodCall.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableBinaryCodec.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableJSONMessageCodec.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableJSONMethodCodec.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableStandardMessageCodec.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableStandardMethodCodec.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableStringCodec.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/StandardMessageCodec.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/StandardMethodCodec.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/StringCodec.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/editing/ListenableEditingState.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/editing/TextEditingDelta.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/editing/TextInputPlugin.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/localization/LocalizationPlugin.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/AccessibilityEventsDelegate.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformOverlayView.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformView.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformViewRegistryImplTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformViewWrapperTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformViewsControllerTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/RawPointerCoordTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/RootDvModelManagerTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/ByteBufferTest.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/Log.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/MessageChannelUtils.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/PathUtils.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/StringUtils.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/ToolUtils.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/TraceSection.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/view/DynamicView/dynamicViewJson.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/view/FlutterRunArguments.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/ohosTest/module.json5 create mode 100644 shell/platform/ohos/flutter_embedding/application/src/test/List.test.ets create mode 100644 shell/platform/ohos/flutter_embedding/application/src/test/LocalUnit.test.ets diff --git a/OAT.xml b/OAT.xml index a1e1a7950d..1f58760888 100644 --- a/OAT.xml +++ b/OAT.xml @@ -137,8 +137,12 @@ used to filter file path. desc="Apache-2.0 文档类文件" /> + + diff --git a/shell/platform/ohos/flutter_embedding/application/.gitignore b/shell/platform/ohos/flutter_embedding/application/.gitignore new file mode 100644 index 0000000000..e2713a2779 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/build-profile.json5 b/shell/platform/ohos/flutter_embedding/application/build-profile.json5 new file mode 100644 index 0000000000..682d223d55 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * 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": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/hvigorfile.ts b/shell/platform/ohos/flutter_embedding/application/hvigorfile.ts new file mode 100644 index 0000000000..c71da0f040 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/hvigorfile.ts @@ -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 { 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. */ +} diff --git a/shell/platform/ohos/flutter_embedding/application/obfuscation-rules.txt b/shell/platform/ohos/flutter_embedding/application/obfuscation-rules.txt new file mode 100644 index 0000000000..272efb6ca3 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/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/shell/platform/ohos/flutter_embedding/application/oh-package.json5 b/shell/platform/ohos/flutter_embedding/application/oh-package.json5 new file mode 100644 index 0000000000..9472ce4640 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/oh-package.json5 @@ -0,0 +1,28 @@ +/* + * 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. + */ +{ + "name": "application", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "@ohos/flutter_ohos": "file:../flutter", + "@ohos/hypium": "1.0.18" + } +} + diff --git a/shell/platform/ohos/flutter_embedding/application/src/main/ets/applicationability/ApplicationAbility.ets b/shell/platform/ohos/flutter_embedding/application/src/main/ets/applicationability/ApplicationAbility.ets new file mode 100644 index 0000000000..11cc563d8f --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/main/ets/applicationability/ApplicationAbility.ets @@ -0,0 +1,55 @@ +/* + * 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 { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +export default class ApplicationAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + 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.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/main/ets/applicationbackupability/ApplicationBackupAbility.ets b/shell/platform/ohos/flutter_embedding/application/src/main/ets/applicationbackupability/ApplicationBackupAbility.ets new file mode 100644 index 0000000000..10ae96d625 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/main/ets/applicationbackupability/ApplicationBackupAbility.ets @@ -0,0 +1,26 @@ +/* + * 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 '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class ApplicationBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/main/ets/pages/Index.ets b/shell/platform/ohos/flutter_embedding/application/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000..81b53999e6 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/main/ets/pages/Index.ets @@ -0,0 +1,34 @@ +/* + * 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. + */ +@Entry +@Component +struct Index { + @State message: string = 'Hello World'; + + build() { + RelativeContainer() { + Text(this.message) + .id('HelloWorld') + .fontSize(50) + .fontWeight(FontWeight.Bold) + .alignRules({ + center: { anchor: '__container__', align: VerticalAlign.Center }, + middle: { anchor: '__container__', align: HorizontalAlign.Center } + }) + } + .height('100%') + .width('100%') + } +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/main/module.json5 b/shell/platform/ohos/flutter_embedding/application/src/main/module.json5 new file mode 100644 index 0000000000..8f334feb3a --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/main/module.json5 @@ -0,0 +1,52 @@ +{ + "module": { + "name": "application", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "ApplicationAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "ApplicationAbility", + "srcEntry": "./ets/applicationability/ApplicationAbility.ets", + "description": "$string:ApplicationAbility_desc", + "icon": "$media:layered_image", + "label": "$string:ApplicationAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "ApplicationBackupAbility", + "srcEntry": "./ets/applicationbackupability/ApplicationBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/element/color.json b/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/element/color.json new file mode 100644 index 0000000000..3c712962da --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/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/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/element/string.json b/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/element/string.json new file mode 100644 index 0000000000..a4969eae86 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "ApplicationAbility_desc", + "value": "description" + }, + { + "name": "ApplicationAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/media/background.png b/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d GIT binary patch literal 57364 zcmYIuc|6qL_rIk#Su&MMQlYU)cz{|$Qc0x~A^BEf( z`{n=HaSk>%wsfNM*uUkN^8dI{qxxW z*@b_`#>VlLWSG9 z0>QdPQ-&i_RCVdp2s$-u%S362^SHV0`EO6;@n(xK));G>#qwhPWrDXGk@OBMV}H!J za!48&`xhWJKj{_+f3ir<>Jg6Ax<&Xgn;)U7UJyAw{(u?zlf{oLsJTS-_o1?+lSg-j z8fcZj1*Ad(!X>WuuxM!H5t@V3*8vLL6`QnC!q!BwQjI{yk*;~@|3;B)`p$WYcDmnZ zt`R zr=oS6o-D$WZsYKh1PiOdhhX&YWGOzpc<6ITKzr^zi-#>z){t;yz3tu_a!>)(tTU9d zd}COuy~Tb}UIRNX@aVGJqEKUa)1#E-u}pl!sY)z4cu+Hu9==`6=0Ob#x-%q}t@jBp zmoiZDcfF1WL{PB0ZO**8yZ+%;LF6K*JDUoHrJkl0Wzak+Y%E( znUmuA^p@Jv6{%Y;MsiZ4O?#ID2b2ssEq6_KGL z8T%zdA3YhMnkBu19bNsa_$$_1^16jadx`0ZzPx`M%T>qZpYyNYOeDdmqLTNWpR5T% zOlRrW_xNCD+*3_WSxvt4P-@qQ9g_$aedDk-hcV~t>Oxw;UaAk1V?9m5<2k4%VrM$- z?{KH{)m_U~yJcBbX+vqVfq&4)Vf+FvAHd|s{V34=f#uJM!Tp?b32THmfzNn1unwY& zPNtaE{ZZ=OkZFh*xW2FT&fDF?64Q%l>dwdZ#Bg;^v;dAbU*QLEQG@_|ucNXFyx~H( z#h?kJKeI3jD^U~`e`*^zcm?PlIWj|tL_a8NC?HVl*gX%;5PW5Y%ZZ*G=jPn5#o+Sh zhnE>D@Wb!f*O>cZ0}ZT=HlEdoWVWk}5H1S;$vxe#Rv~;l5rJ=w--wPl621jCW}B|gxECKzT9 z3FKlD{=OfN5$J3?Ag0g4F5t8_D(RvO8W!*~?#q{Dhx(Sj=)^9ZlE|LyI?p1NXMWr| zGGbzFN^3)5?P^vfnD7XZo*8yf&O&>7XULUUvhJT@rHcF>PmjodH~u4RSmX4TH?v`IKg2cy7 z(T@e4&pPRHRczikEvwvO?jbblSVp z2qpyT+LHUFhHwcunP(^h)G#uA95vF`Gd&1k%F@wuCk3DnjNjw;b}*;dY{F5{7tNsg zLf4y|)RTV`PjQ^!NoWB3YA@S@Cw zUAr?mUcn7g)n!3J`D7*H`y{%TuT$wNY;))rP(y@kdFdPH#h|rjcW2#oRybxTchXlQ zwMW{bVcqRRc_2r^tI)Zav_+qLwdd|Bw=*pM!|pflbT%K&Eof^{6+|k{2_;HcrWd3? z#z;>@Y3dp#B^R5c9RhH8lT5MRr*;>xd<%C3sV2Y}>{On@a*oump`g#H<6V&DKeZ-?Zic$S$>ulEiZvJG8kHMeSzVE(R|E-<}cEG^n2E*Cp z-25-DQv_Mf+&WhT3r?23Phid$q`Z3HE($RgC{EJA0Yc1SP6(a(oZ4RU2L1~H6k0Q< zHY1Mj{)b(ll3Wr=HakbiEk13zYKN&f#9*}tMZiQ7h@Us+N(Jk`aWQHf)r!ObZAT>_STJuzjuO{qHMlTjN9^hPZ8sZBMl zl&MX}xk{d5VUEInRK9r^Tnx#HE2;hFoa7?NDufAxZV6Mj9B^NaAt4;oStAtWfVg8< zjQAfLPj#u>Xp*sALAi;M(f1>la|_-k(E*-1Sa_Vdt$KsCNAwAbm8CmvpDbwL$`Cx8 zkBC0&3#@q@7E3LVtGQcrGS=s-uh6FHuC)WTtU_@t5c_T~`Wv+F0Jd$a9s(?ucd&l{ zWThjQ*u4YqU6Wq{+^0sC%S;vXx~qO|+s%Am1m-N}zkd84>GT;5u}a1*p9&!g%3wk2 zl=rj+H9g>!z4_zdU1iItL}Zox?lwK^ykQ+_#Ym~p>s8CgcLQYV4wezL^K-_HzM$r! z1m$U&G13HqDckgHschNcoe73o=)$P$j46Y)SnaZK(U|F7d#{AGb%>@b+jX#5*Rf5x zq}@ejPTyyn&&@n|dDGl-o-=XF%6dndW+}@7JDd?6b}Mt-SX_GV^3{!3Yz5a~X@$Fw zyDIkaWq*rtn{8knumG6=yF(6lzQnq)&M@%8RzdC%{%-0Ey{v&0pp-aIPP$bTrF|=~!MvLftx2pd=0-86i#@A;;(b^r-TzBJn~W4d42|-V*)} zt}h95!TwDQ%xWD9TFS{BwGO@d9P>kia=+LQ@r>0>5VvEV8(&tEuw%+YP*Qm6KzZs9 z#qL6SPwl9DtPZ{0`)Vph`^ryNV|=I7r2Vf@LrX3<=$f6zv1^z*!<6j{f$|6Jw=%s2 zb)|d{?()1m_Xoab$B5r9#&taTI^E@0yTQ$UB1_f0nc<oQhFOi;b@!o=y6w&Tsrw|K5XXEJEA>@Eb?8hi( zlT-*bXZd6g*C+W9V6B5iF$2f(_-ek(ko^JW%$@}`#GJVV0S8A~FwzM(JdY)c1B&ls(qJ=bvy&S10cqD8@1Clbooq|3kmbD_she z@O#tu^ibgYfM#HD%WIF%%uf7+)sc&Dejs@WRQE+Q1jXlN2z>9dB;X9e>Y3a-&-A;T z>||D+o$j^$E>F`4y02DTELRMYH*biv(5+ed(cQq&82Gu z2~UNnOcNc&MwT3lD@S}nPJMsvOT%0L{`dN}DU&^Z#6?2^aE!5ulUV_Zct}2~K6R!_ z4ReuaX$@AP?M!XMpi&ZJwsY2up5F-xe0{ym`9#@pr%63v->d&@UoFthcC1`k$L=ze zYX1{xl49Q=z953h>NzyMc3UuH96t7)-k|lRw-P=T%Q`;dC7@r`uCOq8Eqi7gKC)~7 zb(*Q>H|T2(e>5DVf9nswM~C%V2G2 z#B|VOitZm{FlV>EydvsFF|Ue~ium0%0KOaFiMOLk(X}jHq@dI@*AM2G6XzCU zSpFR?#U4MPz~VZR>RA@a!CZu45#f<)^f#kJ+ULtRLJKzSj=cf+NxQ}Kw)Yme6wJz; zu3W=Jz<}rEm$g7sNy>yr-Z|OiI>qQ4m37~);`_~Xgr~N4wOAssk(HTh5er1XtFm+! zb`5FT&FoKA{ADaUP!Y#o^sGPb?mT2wBY9ZfQ}ujLk`C_dyTvT&)34sj!RXJcZ%lCzF?kE~i-xCSGh{ zy%iUR0+S_JP(#%W9!Npk=RL(8tFB7(up1ms-Q#8 z$-{dva97!EQB<5#@0KgW&2S|ddKN*<(?}37-=O@1bF668sG)3(D61=Ech&sJ;j|An zqu1a;`}bcMj;#tF3l~&Ue9ES7GRw~kIPKK&q&^No_3M#yjp?ygI;To&wcXbe%ju*z zpMI!gbi8@{AJVkgXR+py{dMSfko}H`^q^elZQ-5<2bG-K8tYq8Q@*4t)`Blvz!#v> zE;3kk_e^|Kew4?}eU;3n)q48yWgAm)d+F(;W(>jPB_glQLiH|IE=EDVFI*j_FBebS0vXyh5@x9LS?RNi7vXf?RckfXjvy^Pifki$9G zzwp&k7S+aNOI8%DUON~#xxv+a5rJDE+^6;@RcjnwKZ|%#%Ukq~@&vL#Pts;`f?jwYL)Y zDOROB^T8hlFfA@(=$bFYKWy{F^5$#{h*A1FG5GZZ1?>Y+!}UULap(oEekfHZCJkpC zppRS@+Uvrs>_Df!YT#HWpuaEwRq)V49)TgZ7Jf{A6@tpv&>tG)c9F&eZWo)(tDPDB z4Fkl6@ov*S4!gboeokhZ>My7@q%!Z93-zy>Y(_9axnH2W2Ie&#X2Z->o1A6ZoV(OgY z@PpdL`E%U}QN-vzdLCdkVX)Vp-z|CGg)^e06LvMfbj%1)ZdXNB>r>{Jk&ApwTkkLr z-2C5e31{3c{*xsm?)EItQ%pSW(%723B}AHgke#M{7KJW6TT*>9^+`FIe4;VHRwSF$ z9rBta7_>vwCuV;vFY=|NZ2KlX$A`EUk*phH=Pd~I8Kkr|v!j3sBAD^fPD!FoPpnHf zqP&jc&^s{jm0M&oBNXjUol2${7|G^u7UtOd2kxA0b?japS#xlwo_TaY+jh-`+$sfO zFLgfqb~kaemX{ErUn7}?_tb>g?G@UyT99HoY^;BG(5|gh>F3J!9J* zvrz6TP+;XdE$<41%Vony^Y}i*aCz@+4v^38p)5?Nhw`m%Cbg5Lpz%VOxaBnlA9P;N z9D=#{(>`$N_!?&CKf9eJGzIc>dhWes8XtpX`{gOhP;HMklZ8~@Yu~YT1bZZ{VwrAffDNiZ6Mh5vEzpq z=5A;0ff@>1MG@vbwRU!?7ZFD-SYng>JN(=>uwrkrl@4u6M^n6jl1shsk;DM`t#|F? z(H9W(@&~b(mmUR)30H=vAZdIrX%9iR7rMruZ_I4$Eq7YnBI4Z8T zj5;RTUu8?(ZsW>30%Hk#$^zfAtgZ&y!|p@5%e_4oe7)3{Y6c^x>zv=o_XPiF*wI1y zNe5L3p=L;8_D7-+5I+LfNgDYrOIUD_Iu_VJQD^=4v=Gd z_u%h$8{Lobyu6%VkeZI%T_vssgc#J4yD+&6pVkdLYl@3@NdcQbwl!J%4{RC80oF1z z`ksIXyrZT=Apq3kOR#m795+y}-8NizKBNESZCmBS#jqG`n4kCydp-4DZ^BF-zWD2# z1@F?p*^9m)EPrkd^E&cimk<1mN+iwSCVTHpqz^#`_Dj;-5xURqxK*!kp5asE##*=< zc{bFC-`m;q4VL3=| zKN6@)%XIu=yS*-K-9Bw`jN+-lWBttd77x>|g)~$UgPB_qH0h&bm}j3#sdLfV&xcR^ zQFk=d3;U8~YLqm@^61C zmaLbHw=dJ0oLP?>eyJ&=wgtZm!2mS9V!i~62x+n`%jyesf0bKruxRDH-)c2uF;&qT z4Z0drBbHg-G#ueH1vVaEJFTw$U))8mlUjFz?!PDqNpcIqZ%B6$Ju$CzrK@_na@?na5LpJODS}`)`8j7i#>C z0RNEb>nnQ8v$qXrgh)-(=VVRFwj4 zZKH}5T4rlZ$PiI2z3_*{`av5A0jPJY!Y*RQ?XbKPZmNdwp6ufAH4m~1%r{gYeOJBR zai+gl7I{Z35P0Q7EoGmkkLGHe5rR^{bdxWyMiC1~&kI@I-bYJrdGv{=O7!p&kKxN3 ztOoyzWj_asX!zA>`fa~&>#$n@3{c@VVcl3(1m5=dCI-~1uR+4s;@87ozKCU|Z(EhE z7~Csbr}e|&-zPK~*W}WcKqB+rv-rNRzvqfY299AvP zA5u^Rs->xN6b@MzP_f(M+}|~RxUHs#zO%D772V@B$F;5<%Jx|0#Oh_?#%yrHfV>}I z!Lfe59_VCjJ!pEQOWyUr;CdyL z-RzERMQjU_j%}N!Av?++44uVMc#r_KCTZxxSZL>4`xbm)#)*?4I#nFDOZLv10s^{6 zAyo6zfA)w8n^jk|KBb4J;|Gbx9)grFflY-Nyl_v8_@}gizDNn(Y2l6TqM&aN(+9Qg zTBo#J4N$h%f!;K&2NqBlT~J6aqHGy6HI`Xn*)UV$w2>iLk~P=l)VTdah9Ab`z%}dg zxIvG$xPG=H0NRw|6_-~Bzh+BPv9&C;z)58?`7t~$HupdHcF!F5dirrGrn3d}wAHr! z^@&!aoW@3sENjl#i@LzRYOZ4b#v|Jk_Mo$-VYlgbE3LQVKniS1mH)uO`90X{bc~{1 z*%Wm4$E_2-W__`4`mDu;Ld(wv8e147=mMu!AKSC=mw*4n^8S>~fm9mJgf4~8t(bb> z^_3WSK>aAZ6lK3OZ#_7g@)?z1#pZ zoR2>rm%_enbG!+Y34#Jmal)V9@-s8li+_Le^~z8cxHeF5vR%p~{93TJv%YmeTB|@^ zc=}q4Gofbju_Z#%Iv9|44|pawNvh^mFGBA_KZ5C^rx-l~Ytqf4;%SxezE8%O)aJh& z>2it7b`epB=P&=s^y`mJMjMq&9Jvpdhn}6sFHk)q%d zE_RV6%-}?H)w7yAW9TA)&7XbMyu=N}tRA-JTl2iG6u8;@?;!BW;ykyof{i+alo zJu1v~ITow6y^)5crWdi)&;yNs0d)3*vN+aSszJ%`1`(%9X-Hi}3gH#iRg@{Svm?cP zM}T*)U{A8FTQ7b@oc$7vr_EeTIj6N%Cr}VI5VcfZk+@1UFc>zpJkm3S%cb<~=~`BV ztbyjzOPJuDkTJJ!hL^nLk}*=2EXd?->%+3NWrq&5a$%1G{r2~cLQT2W>8!pd$9G;K ziQIDUErsVk$XQPRm)pDFYVuLFlx&eiFlnoixT|jvAoB)ryM_}euaYFXrdKLqi|4AL zG`rnvWi4Qa>Wvo=;Y+t@ecMjl{#37K;?VkYdoSbT(2m}8!k~RT{yv0l8cPp{jtiXr z$7KAJAvM_g4ak}0Yo*q!sO%PN_CK)Pv>lC7xoB~vG1hs?Wv>^kpOBU0WV@$|oL!cE z1FV3%^4Pjr5Fqc)|Sv+upxx8BCM z9*cYQYi3jY(^pUL8`I|3rHf+5>sq98e!hkPsfNMQ1@y7Tnf4{F2p zx9AO&@zYO;WpCQUf4G@!d<{t43@&RHh2Ukg^D-8_;De`dc{hz?yPS_7BzU!x^P-tj zBWt_uk{g94M1uo_&0l?m1qh!Q>=dKy5cx zRa7mv(}`xYKJOm)h3s8goQ*XK1OT<#&Ozf35uTB^VD8m)Z6Bnlal5r-bkso}J^TcM zo)ZSc#2@`h0Si}lrnCFt67JFa*e&}2avKCL|IIk<$R2*5sILkv4P( zesTX_tP#NqXN#>Q{4oe!N=G{SZ_I#~%^kq5ilGc=Q63_5uRt!D^j$k=&$`Ha&bGlAjZ2&hWa=M};Cw|5onME2e;8le z)-hK+mgNbGw-4puLN6g_q5p6T?0XM^dMo810rSBSw7Rrl(jt2JNVBwhB0o3``lZ1y zBr`Dy8LdVilxv`X5b0N8#{#(y<2vQrLj;qv`XA#RZ+@Q~*aYa^UY~;#F>6BL>75+E zeH2(L#HhLeI=Mz1#%^96zY$Se;@N)biYOvM6H1p6-4LcvA=&GP()#?u=_WXgAoZl* z+bR{6BA52?12Rex)v?(LMRsKvf9{KzP<^4&NISV{2!a;wEhr&E)EloHqSR9%ezb)? zl9X;qQSTg@es%UevGs9-KQk6RqJ;Ui(v@S0=JpkXQVYgXlRKQcfFLT2A%*#c?7(b} zjki==Q^Y#Qf}ZVpFtF6<4SbGKkkU>I6wY*Ps*EAzemS5Z0r!-oD>~r!<<+c~fHK+{ z`u4nWcW&4!()0%2>r>@zr$F6$;5*IAuq5bc>cn-IEZ+B|hkO&NPeBi&47YiU-<$w0 zq-j9aGH~K;Y%0{D&e90RZ(J_@o*`(e0TgqWM zz>V1_2|7MMg_6zbeK`A2oW6>`dUuDIll*?4hKaK{^>2t!B*N9o7_!iC51?A=hss#S zTOD48mGM}}JkMLeB>f0zNw|zPj8Efyx1Qh?QyT7Bp*PsC1%+$kgboSqDR=rTEs%8X z-t2|68n3XC`A-sBYO9tXuQqE7{}pE3mRASQTvScN7(%JH0{M|k4t%rE7xh`qUf4A- zgEE3f#zcuMyMYyiu;w=#PFC-_W0rb;u#{l@E}K0uMy~Ec1MBz-KglT}I_AG%m9nb!XAkpoW-`_85Umy)5g0j(3(>`;o1;w;CKp zLKdGc@@LrE*Y6B#H>jMeTcD6nZx;FZw zZ?8nd;T;sv#~t>9Stu`V2=$pLBHrDq3VNw9{KZU-50LlNLK@?o*hLF?1Kjl3op`;u z=nFLXc(CuUKp%gcxwwBm08`iDki>51cyobB9Eypc5@0Uv%$x+m$P}vtzJ@yXv2Y(6 z%G|Dfw#*GyPhoZ)9Obc;u$h*k0~W zv)EW8ChYvHNP~Ws5(MQk4JSGnG!l*4I-odrw$8E;u9uTN)1sDTSK-9%H|jqRi1XpO z_RLbdR5?V7FZiM9a@_RLzrIa?o8u(&ct}&dJFEmRO#py=1J(LW)$S@B$xLi6T)SOw|;fa7Myzv z?MOZ*b$o!rCg?J9&v6SsP#m&goHWvlC%0`IUKT~X&=s1cU$O`0Ea`_f|aU@(<=bXW{`6+7W#cu@H9t zagx-Usc&&vez&!Mjqpdk+Ol(}Uo_B;A&JhUaOe-iG9|*Z<)SYRZ;!m{$5X=V;9Cl+ zs(#H}WR`823f+9`wmRKF;(;wyt*?b3@Y`H^;&@1GipUF_{Gb_RzIV!3$qMq++{iyr8Th+msVi*eA69cY1K|TmaXNA-rCXT%k z%$21aDiQY_-+BI`52BI$rv}FI)tg7-CaaD7_O`l9ngVYH9#Xu44ly2flHy-xuzEyCWC^6c-^K*QrZW zNG1PL`B#xfh_CD57q**Q+=Ty9EEolHUwT`)Z`SWJPvsxa-f8_iHO;AQOj^^?v$Pd6 zy~3pjahT&?UwB@2zW1)s8+UfK$SFAL~tHHx3whuvPyW4mh3w z`_Q5~nHOsoDT0sx@+N~J<-Y&TvqV4MCkgXgo^ntecjdoSopR%@?wkEfAuHDOIVHQe z|K0}d$IAWT3jC{=QJCD$*L3=%k#f)T)tT7R=nTHqn)i5$Q)sm)53ZV1w&{swK_X#n zpD3;2Eb$r)$CDg__L8tv=0-5U5hB))B~SI2(6`QM95phAkktAVs0hU305vOGT{|^t zH`?>)3!24y5TBnjRfAJG|J9jjj_JYwB?gujfD3QwPf@~K(A2Z4KynC|m! zMt!}`yx4=~u?@-#ab5-T?In;dGAUlGajcN(yFF%ypy(av6(B6-=d(A}}k7wcgUJ%c_TA&p~<@ZA~EU-mvx5S_ykM?O8{R|mH|RE75BR5QQ#CTpy{;f{(N zFpFjUOJ}EEwov(%eX6wm&~H5dD|PO&*VQvG&6Br6eo1I>i7L)sk`T?{8}`lQfCB2R z@nDF(51Rl?^;uv9K%Wz-qpmyIoZjoO+tGhY)P>lU7U1Rpv;b{^)mu_I7=1e%POI7M zneWYe`!E(sG!D4Pm@9XD2!jhItDw15w=Vl)ioN}tjFK(3~fxy=!h!`6@!cQuCP6#aH;{{dyV2@O1#ZX{Zl4pLmD z7*{Ip)`V*gV-QVaE+>|4R`><5Z1*;n%pfkb3AiZ1s39)5f5khONJ{XZ5dEj{AwE^i zj6G1{WVlyMNlC3!_Nyk^Z0DjKo$ha)xbx}7UO*rnNj8he_fyO?v!so#$d4^uhxAXf zZNG(a)^5wM7^{-xB|`JITdre*!q^0$>^GMLKm@oauH?5G^;l>0Hp)xxzomAmYTE02 z+c%CPd*0$Be%v~(u%mMywt>EgIlKPOZH{Q%Y5c6=;F0usNLUPph9Xez1H1>s1YOPG zz|s4D9}W5qUuupaM_2#&;|@Jl=mK~Bc0i~OYb643=Gzqz>i%czm6IJ}e-nj~`8ZFe zGWf#c?5=VP0hlqMCIlRJj0p>6ob8O5e(*AYuP~QI>C$d^Yi`)_a|r1LwH(~NZ9P?Y ze?ts^N2upq=Br??YX8%HZ%xopU$9Z$(sjX zPFNIynnhW{IRi^L#G9#+Ew!gHJ%T1dibisJk2~6dM4r$&WR1@Yh3+PZbrp7G519Z>UKXw(mZMT+M-ozzkggshV_x`b zthj%~?f*E&m2-P{17aTUsk&fyuduoa3w}G`Ii-fByRE*XlORaY&Ax;2q^Y}9DeUiq zyMK?>G}eX;GkTjbS%GZr z5T&~;Y#yW|>Ep#W|B^P_r=X1$4uFNPGyw?zjr2lT?F6>ZQaaY;=%~?w4R^35Z=yWu z?(pW}`Hbg{7^L5u3abb48R>Wz-8&e~ld& zG34mkg*Nsz8LkANRe$e1~y0OAYcFkLVXfFw#0X3 z=EB)RkCjS-zhk?;_Eww$ZWCeYf2AIt@_v0+O&5H%+nUcKQQZ*-D#Mj9~nh zx&c!=`cApy)!}O~mTV6{@dbum`*7{`e8wKXQ$qf(L_&%pEl%&9Hz4Ua`%w=5(|{Fe zG=KtAxRHvVR%isJiC+qS)RMDX`xiqORyFg!x&NkABWs5}rYfi3W6r|&5P*I>{#$0n zSspPdl-FAPCWDVqU+`hp5SJ)}U4;QxQ*A|gM$`7-D_HnBBw1Px+%y8Fr*ZBkK&P(5 zLO)g}sM)3#vqJr|zOLiUYMzC)Ip0^+BMHE(YMU_d9|WolPeKCgmx*JYTE6;S>Wa~2 z4x7~9yMFQiL85QHvJtCUi;sWX->6#j?bP;4-B$$B=t*-7v~dwa7d_l5=?cxUgm6Cd zaZr_|B^X5;{k6{%BEZY5G{tgIXaw~PMvhi$_PDnHbyno3v;_gj5-=Qm12)lz+O@kglm5{q;M_RZxMCq-* znMrLfk)rYkS^lo@-6`Sd+^FUeRw9NYH^+}naYE(H+Zh38KI`SA9vUIYM`w7n(({Fc z<0<5oW06nE*}@UB$5AV7a^dI2srSJRcWrClmn7EQdBmJ6?_NrBl@wo_%pe-;K3ph= zN1j@y%^Bw-|7I#-OsQL<1zRV2i1N8h%Jz zJwR0GxN$z5cL7T2`h@=Nn-d!(GsG9!?+6zh=pQ$E{l5S3TiBHQ1&Bvy(*8{} z3j>EOJw+p*2|#VfcRh@u)N+@NMx-@QrQhRg>Tr5cY}aHl3CA*moGLkK0}rdRVR=E^ z{#;gyR7l*RccCrEo*H}%3X|@5YPQ+FM>u|=k#sp-M{J+EGRGl7LH4Z8UIUZqJ%O1S$-a-TXZC__K^ zV}HQ($I)a#fHDGwtEVN4+}*Rszq5|ewZGZEuA5Iw2OpA6%g^thr!`g2lSe?v{V!Zs zZR|Oezz_e)(WIs7nejBn3Q;m~{el(T15QaA3slu+pDiHa->pWfN1C6rVtf%}cuYmO zgKLKj2iNqdxC5nzUkN5bWkY7QyW{~Jm`(yqq=456x~COUo&to>DhmwrE0T1u8eLBX zmGKaO;crc6pm6&VjM@?bZCAXTbba*pRUvkbglVZYwEkF8YfO`T(Y8Hj5McaI z|C{H>yx3qKlRMuy-lc?Sc1!2)CVr8jr{HCfqbxH-_?m>w0h)fl`U3oh{a{=<4u=GG zzB1dSG{rJNtgG}nPU<2q1UPrW{mUkc8)_`L7OAnol7dZB_a(SX@-|yK8Wwm(0F1NEm_aN1wVsURw>% zPcJ-K`1h9E5@B%#7Tn`q0}2)m8v1N;72R}2#~JeoV=z!u6nMx5Hh%7WcQf@>B}s}j zpX2a$CtQcsC3W?=6QyG8m#bS^7MwKolNJR0blaxwZnvS?S;Zd`$Td4sdlY4B=DpVj z;GB--4WcwwL>bZgwia+-FoH)nTd?9m$)`kWfURntsPevI9OkDUq}At_Fhr2*m>J<7 z|K^#22*1UDq{{(|XIx*ulqtAAdQ3OrRygED^IBKe*@i}bZ9_@AZve0qu;T?J2LZ}j zw%cP}y=TD%H^Z>GUW2*063o&E!US9==;FnvZpXFNHRbelmmD_~T)}7{w z&e;xBEsak%$=pypJ3t9=dtnbS!6w40@X`hEdjEiR%*$gfB`8X5t54B?{Y@k+{O-C( zyWn|kD&H^1e6{Z}+mjH!-{_d1n-62-&sj0eAIe`j`?O4m+Khn*F7;(ko`grc}wJs-Gcu{X=-q9>JtlE}duQ+wL-kpryH@ zy?9QcUQwlU%a{$3@vO{6uEg-;vQ6$i3UQK;nO(8qR*T1<;wvvr-5aev6Kzq@WY?yI z8CkJ-_v2o5#Cy<>1tkp7W+umyd18ce*OX=Fs(i}ooB^lb_(Z+B(#0c+peWSQ7vamb z`z_V8WZ6ITb0VsHVCX3uI!$aMYq+2H_VJv|H+xOae}8%g0Ho5T!|3N(fPIQlqqpY} zehINqo%!U~bwZHmWWWQHbG6yOu;gWGMqLHRHz7_bwPG8clq4AvuJY+yO|fZb!!O?8 zu}-gsTJ7>_YGOwb9ZP{7Y~E_-54t0uZ3t;;kkys%#n||9@a5P2V=teS?-R*n9l4LU zX`b4bjK#bVZd&U8y01tpmu%od$DMxAMMv9l&MoL=#mqz@UrVGR_l0_DR1(?*60e1Gde-2*c+IsqkdsUBQplCu zbAh}kVEU~E+wWc#ljwacB1;-}=6;qO#+T9U6+R*7gTqwax52TW8BT?9baXZbe&3!{KI_6)y4?e%W{LkWI2jCl?{Trz8L**uH#O^Q>E0F; zvZVDQPmj+y3P_#pP5&8F;btP7L{R3-N@^b&z}P6C*IselB-bHG;@9&O))tmx7<0R@ zq~8V%kqZ)eZcoE~O~sQ8B8+i&1Ue*r4H|9dY8S&zqWooS;5LT2)V0emG9SEr9t7AM z08Kh_ER&MkZz||l>!~yU@mi`?QQ4AitwkZp6F1DCU$U*G8x922-bf6%3pYrD#i2*< zwpz(G$kV;(&?c|bI?kVkWtK(xu`&B#;UTMoJn+{-FXYMJH&~sfC%3D^A2%%pYB~Fx zYFb@KR!L)a;xpqnrzd^@O_;-5c!|es9)R%NkQ;Y{;h&+Ck8^jTn&jZ}P=M)n>!7A9 zbI=`ms%#Cn4 zcD|SP<@REH*!8~greM*drUAx|97aK~i?nk84xe+fW zZ{VZUt^WcR{^_IyCA?BgZ6gdxVu5?G1|-aEz1&EUsaWP+cJ~=7?fk17Km5W&X3{&= zr6*juZl+Xa>izM!qk7^<2X1*30KepqIdjyV2i+e+zNXSxbK7Tpa}Fm~tK0+5Cmz|g zd=qVePKdNVx^>DVw^plZ?2M6Lxb`!8Ti#RkyDG;^w5l=4mTJ7GuF?>G>j?|lQi82< zNSi&Ar21!4wJGm%haIm3(&qHRaalgKQ+Zo*VUmdvO3d*r$tQiZdevGg?sUI{@hBMB z#c4dG%$ziRt^bWNf~3wy9fsIN_Xz#^hwnqZ)3n%{%nU9mIShVGJbF@_aV%R@{2`Bd zRRV1z;iLf8vnhQhV!*)}h_XFiU+=HG5zruPk-I(^EEW2+SP43iUg88Ktt+fn{a3`C zxH5^rzt^)}NibifBptLnWW>O$q<;o81Ytp^|JHO2c^)R9nQizz@=pua-L?WcDwzsk zqLYg1NS}l0EoS1SEwfU_n>3wtIkq4r(>>1vzP9Z)u* z7!cFZk(y94Ta9;@KGI}VuVTz%OclFRP84+NBUYBAN9)j18h-Dk(N_YxRc+#$@;E!G zk3>;{dx`$+A4-y+OCDz=U?O~&oq10pF2=@SEP`h*hn*uC*BdqRBV;NUWL%7GQwvf+ zy^@Jg8oV=aF&&>FIZfBUhPx!`mVdKBuW_kcOjuX6o{4h~GUS(Oc#=*IhjnUUK6V>q z3|r^NJ1i%lyLPs-RMaW{5i$=F!>FC4M0Pj0<<@G%muXC?eGi&&ai*KS|^#9Ba>V z1r&49PJmi&clkkAhrws5!q)&@Ng2>63rG~VPQPfM6P3_7JQhw!k2;x7`97!rb;o&f zj*N+5e^fk>D^vzYxcBT!!vc`_!+5f!_>XV3z@oz}r2l;7v?ybOOoLg1yQEm1p==et z8!M{V&DaVz@Xg1^2sOzN<|B~4p!Qqom;IvMJuhY^iq(pcg1vcJBD)9j$F|MVwyRM%Pf=l_jD+NyPHL%YE6 z$(-O5y>IX=Oj2(?JA*YBgFzC#Ok z9`8k0Tqim&9(eUu$uOl3X@wSOFmmcm0q`1mIA64Ve_<%3$nNID@10j(FXICMN0-)z_1h!Y(wFt@%rzn&KWkzAN|(aV{DA=J;-G z#?ZdfVo{uhmv0)tmnXPt7NlYVPN%)+Ps(HATs zB#a;EeCAVi=f9W$o`(OvXpJzf;CLh}-04ibR;6BeF3%HSpb7P|@BS;Ns&;?bSOo4F z4DlH!B~h1(AX80$!u6fC-}OET`Dlw`(|?}OMDd~ z>qFr8tnPYIjcmoZtVUn^-ei%&OQA5Tc=Z`Iz9m6b8v)SNDYgGI z&ufpuaQSeQ_2BtH5K)eKXd4pr>O-P(?zf3-LUZVNwLsusL-~7SqM_*WS%%V#M4_TG z{P&M5x)q1sQS4zgx}C=u@Q?t@YU*P&n!}ih@#Hx{2kRN*I*QhP*keYtJ=k?c?y9!B$5bcgrQql3d(MDOE& z$&4)a62X+@f)63w)4wmU=x5`h3F6ai?c0HhJ~iZLYXK!aa#)hyA>2 z|mZaulq=2%a+*w}~-#`f<0;rmBC$8kUReVyk83I8Vz z9h*!SORnHE+X=(t1767g6#NDfz8iGC>whkQKj)G}l@4r;Kv22N_b&h+TX2u|j7#Oj z(K3uiNL1XY*yk@SMq0V^nF^C4tY7F%Xkl1!XVbIhi9k&fR@zT?lM-aSH@RdqE*fzT z0x=nU5YhN`oe2_Me7X&Slwrh-emZTam}o^KV=~utowP0%qBQVdeF^BBD(JrsnqT=g z0Kw~8J^_6p*PaLgV@w0$mjgf4%j*&bCxW;?u04g`wLQC{3<iiFFlUUNQ@-0`3U0PTr^* zMu`6+{ji*^jscj}HzT-Ix^mFBSE+}Zet434IpXr-z;GbHM|<6Z$ud>QLOHm$q>Yj? zi=X^?XVKh5dmh63E6q?c-(MkM>f(9y>kJ)X*W=($$*zh%V_IowxHcM_Px=q^tBS~D z^CNokYN*qIzqTFLw@*J|W1E6Y93dEjFM7bVH;omm!&C=Z%kF zDZ!5^rmEV)HlD6O6Tr*st_e4;^fb1cMxb2+e*K7{dMXd+lY~LT*&%qoG(^LQ;xu2U zlX&3i8OG86!Vntf_USh9iF4*U|J`}Z=mVM)PeAs{D4WZ*4$7P zB%t)P&$2Kr04o8Xy;J`g@KPzWe`1T}m6IZ9MOy`GPfato?=$ik(>JsouPv<{^B1k$GpotiH# zAFc}^jX-(p!24l8(M&7@pUe|Pfm=;J8d^`&7M`y}lC2ikiklLO3&7s(v`TZM_wLvp z)BGvu*V#(5myOg0-#f?hZM~gOm)pbI4r6l2`c;x+BoKN zlf8pTUa5LIE_z>y*IP(5Wwu|3hR`D}LJe2Z{OO%LwF75itx_bm2;*V*L_d!<^U`113iZ?AUR2fo{~@G!O7S z8ry*a+L@ya1s~1tUwKIw=9Y$~W4(^vWXYd@p8Pzd41rg5Et!ZFn)0i|BZzsFQS{Ma z45FpX$A2OpdxJDya+vhWuRX!EMr)~=G60EB#(9=Cm{yUH#1~9tH^>Jf<0R6m#c}G< zi(K*ezx7%l*|KrLE}7Nbi?ghND_o~9`pZ1q-*}Q*Q`{_{6rWZ;i3So3-$FI8e&&NC zWaY{pZS>)b>-mE2`c_1^jB#|!C|63e+q*hQFKyk1RQ#UTkJI!M6}>*G=VmpY(8bq{tn;^1f`?7^Zc-BLmxn4n zI7ms3JW&2@wCq%Iun#b{=0FF4fUU|6)~D`fAdrMDf-%qb7}(_}O-Q%nk`;V~i0&E` znTDr*@a5IOZ9_&vz`~lLmNpX8``JG1kxEJD;}0!4K|3<0TVqBa%r23*zlrBZWH4U0 z5PQ(DoTHN$fb7YEFYgjdU<)3`W~2TCFZR=#A)q&Z+nJ$iP35--s`>pS@B(Z1_+$t{8(iqnGXFSA(Eez$U z(rAcMIv(%#M&j7W?q4q*k#Rn$E zuip+NtT*wwH#{;4u5GD8u}hZ<6@&20Q`j4GxWAW}!MyTY;KIYKaj~9lLj|ADb-{w> zXQV5^!qH%Z=(nxMKm85L9tLs3cFQNel6fR6KmK|2x@yy>gzqqyx%l2?3(eDsLCocG zdslQ2dcLqbO%Nc`$|v^)KCTKql8YQ&?l90WQGtlNjj$*dWc`kau){M=;cMhq|fFjQ_6$TE)+((=L zN}9jU#9gO~MwryIRsj`Atd^e}?`()lD^;B%s>2xr9u$3Ux0maqBQ-M>|74?_%Xg7K z!Rj9hvpde``3walaYgh+!5Q07qw5!{qQ@py4<7ToKiaHbesEVf#mwc)!Ha{sUwaYR zYil{4w$X?jszTm52%aZddax+>6ZVji-I*L2fukc8YS$2F;Fp7qW|#QMx9#UKh&WC@ z@b|j|WKkGzxI%6W_|)$N(vBy^<2S&=M}T&+nZ~}8nxXRO<)lH7nb=UnCA)@o7GYXG zo3mta!~WY5Dh@By(QrLSG!7x6di% zS9=>}2G(da?F-j0X5}QM<)9<2P^&l*D$0iYCMgnRBFhgP;FHiQ{{xc#7njIn&F46G z?iOCDCSZ+j2-Bt2p^J`aBdnQ2?1U{L4m?WeF)8Z<2czjUtR`T$m;{Z_29g z>0R-hEnP?RcHD}C;UCvlJW`!Q#=eH%5m;&(#~y)~Xxx)!XmTP*e;VXL8x+aO(;`p| z^Y7W=lRA)%A&Qg4Ci82P=5l54I9(e#7KD~f&prgcc-_0=Y$*(6kGR#%a+Hj=nMsHH z{nStbI?Mq~mcO0m3g4GMOW%!sg=~(F zHo*;$bSAPDVg*dJd-V~f&<4;QrUGPQ6G10(WzW(3hbT`A_0#Y>R2$q%MZMcYywII% z>aI2%Lsu?S5d6~Z&+thwjJ}cHCua1T#4KIVsE)J)J~nf3t4Di|CU2=n)FGexBvJ*U zcqjy-l@EC24Xf1KX1_uW^(#D5hrp2oIs)xY*_=Xl}7sic0DaxuVQ;Vj(H8jl6{ ztl@;=7&sO8d1Gy79NJS|g5yuZoY}H4{hxfL0oDiPGb?VB&s?rXwe~sbb+Sdvx96Mi zf7XvCdY<~>#8qEs6=adRIh)T#cly&iVqloGZYgq2DE$sBY(0R;w#HyO5m{Xi|j`ryzeJhFvObXi}zQ$^dkUa z8-=*j7t{_XJ~$Hv+WXY=obm2O&HfejylNDi~KEqaO>WLW#z~4D&S_4?L?|I7O zd9bOA>y97h8sWz}k$zJxC8agx00PU z=&q>}m9ckFl0H+8hHU7@QXQTDL?Q5QW~dH6U!?M-P2yvDhHyR=*S$jlFb&0tEg}In&YcQjdt18>ST2pa1*s+G_eQ z$i_(cvP~<#>q^Bp?-6%4Xz=QHw?E&1dQfBsGqE1{N7)PW@SLg91&af=IdJ<2o23%I z=B3MHDwg?zEY+b7?2pWuog5RCD;Ts$p6L=wk|sWaAE$aA+6Z*uB?%5v$opCbw9)s| zLe|cu36WL79#gea+kAOY86xuP@wbA8`P>mQkI<_463)vU;mhz}ev%wYe9GJV8DG zsI*WsdD7gNyjS4W75N&vocg7{z5xOXo$IkwyV2@+8uJ0z_5FJ|yr3t0HolQ8DNX*! z@UtBrYSwpRoJm))>Ui-&I|GfHtg}9}+AglmSHBzP+5p0(>?gKNG`pAQ!o9wA#@CUV?kk=n|xk;NAC7^On%cCA6GUg(8h74Mx zmW0D{fTc@BUs1k3M=8z#svN%Ei)~)D$!SRh)g|_VkdkQiW;lkt?N}oDiND=P-Idjx zkXC>GUNXXJwB{;*6!`ng08u+T37|1I=G#2R0wvra0A!Sc!<9r=?}l{$d_EW{5PB5< zwUrHoXWjP(om^Xc&*V*LNj~HwO;dHpPQq`eu13BY+nHVMI=pjOlsk;VH~8AK#p3E# z1Ayw~&8+%!P<)FVQz)NqdGfTyNTcPU!_)~5lQhDRYkp zC_%1KG3Srg*YlBCiN@6Rz58(IAeQR&A_FooBDOZM83P*b{nB%0neKaT#g$Y7rGmbH zHMCz_Yq+w?u72_rRDz6F4}2GfvaFfx80_zu;fIdvk1$FYLSXCbPQ#V%gzb)_Nq(}y zU3ZOC)Aq>!)bT44i|W`IwFgrG;@_%k*I%D4G6?l|eYRk%UGdM|8h^+cnFz~LymyV5 z5h^5j|4ieG`CvT0^v)hdx>x$4e6v^czfVQlAfgj#Fy_(pxneG?yXsOU8$@^>PX-We zw`wab$am3g+C&Uz4)|>7a*fvwKsEZ&?Ybqt9)qDXf}-cC5E22Loax}F)rj@7O7$(2 z?!By3nfztcBnGSUa1VZ)041(8iYs;m!`C^1Tiyg?|0l^IwgFc*BSY;i+Ru*Uh}%B( zpGlO&;XTgsH^=xdf>7^jmsz*4(_pfM?Wj~cXnBx z$yXh{O^XBq{@qVmy!3{Fe;!W@={=aK2j2UzP5%pMBJj0CeFX*AMz0*|e5> z0wrQ0n97T;j_W9N+s3LX;fTC8`{qy)IZ0K9riL!D!5uE5b9WPVf&!-Q=RVOjTSwBi z;k8~2s=sRnuy~C3mJ|d`StNjPSpD|gN1T; zzn|xTg~NK#smNy7NR@gBtcTMt3~%0kdbzV9%NPq6P)tbZzz0`C{C#mdv%>;Ao>|XF z9T!uW%f{;V^q70#wi`Y&^GyCG4UkW@$`FG>2r$|+R>cng%Ay@aip@1NWmZ1+gcN$V zGh=iq+^Iy7a|>y}@#KfqSDsgM>yr($WF&@~n1*KGhMF{vmm|Fakd5mo!~zM$Gew zn{T}s^aD5dq_;fJQ%))f`$5s3r1`G7tNu9Cv_YzL=G)n86=SkQN(esj_>Q{^f$Q0l zj$sILcM@Rv$kp*t$s4ktEp{iiV&b;eWR+O7^3?$9y^dc_N(V^%wbpl*ZmZW}s~61t zC)3`KlBcpmunVa)|J8NwWr3e`izfB^AQkzeKpWXQY){k@)2p5_!R@8GcPFT#3p_sS zU2P7<-pWbsgYLk%M&LUO#ycYKV59bKe8nkHyyH-9+I^Gtsekp|x9$Vh6x$K2JW4MH z?B97keW}HJL>CBgaJvcIuqZwH&v0t{zp6rmOjcJdt=5#U0gz%O;r5BPbli`~bn-B~x)jPcuX;Qa4p=fVKCY!AcXB)_9R@svcMQ3a+3Qf#anpAW6c zy`hp8b*Np5O#tA*6rhnIK0?8wYULw21)NewAS@DQyw=aryfmQb0zC~6F(8jHAmH%yD&YeYF3g2R$mBpYO8RPkdMs{f+{XJILUCPEi(lE9^uM}al?6z}`_pj_)mbUDDEc^i26 z^#|94ClCxrF#PNB6U=hBSP%DQzhg!rc^sg`bNY4$x@IgCJ_Sk>1Ce0sp47kZzXIY9 z|7!cT`@e6#M>bl%n(^E0X@sPdj`Wk)&2m9A|eG&Uv*S&;NUT2*W&tD|}H=7Wpy5$Op4C z;lrxxFPj050yU58a@~5snJrO;gF|XTcxBFwrycmk?zoNvu6Cu}Gr@DrqBwXLlharC zl1vBO)RIe=mBUAV+QtI_*stF9v3zwjExdyrp!b|Em z^Qi{xZ+SxKi*%CxJR`=belBN2@N*NRaj@ydsNK{UIK2gkP!gwG=z;sfD^oQzTA#La zO5vBp_e3}q=cE4-Kbqa{n-PV-zF=n@csZ2&dJ< zfPr0T)65}Y8PR7?#2yb`jv;P)6TsvSoOqenNdzgKy#1i7h!>dojt|V;PIc}Z;55sXdP=l9(^p|759HpLCBthH#}Aa`oZ`9GAO=*n{lX#bRAm^gh`ld{8~~gycM6iYEUB7zn&$9I}i%`)4W;V0V(Jht>^f zV!k8yO{{Cv1jw`yBk8d85UqHM5mK#FpJ3fnn2WQtrDy9`CEQO68Kxw??(_}4`m&iQ zn>(Hh5S=F6y#FT24V9j|Trq(4`!-UVkr>`Hu!LD=3vz0ks3PQsHSoStgeYXiK=vGzZpKaR8a6rQN!4etGo|kBLTOdJzt8YADqF*68=L zY+4i#i9+9$xs`EF*s$V5G6!#;J-EZDvfDh2F4xfkUa^ny{IpzpCqRC?vPY5~C+HEo zw2A<6CfR4qiAr<&J`>#S`=sNLi@g%rg=i@z|;p+JN}{J+d~3!bwR|1_p_WZ*zFg8JdY2H&$(=>qm|h~`0d88 zWfyZh%%J_j4Dq6hl=rxTCAnU4frH$_ytGsCU*D1mn`Z+sw9>F*#!002LkOF@J|RgG z&VYXmonzYG{uD{CvS4 z2zvgHZG^kGrEZme_YMX^>Jp5Ekly?SG)UqM2$JF;2kQZuO3HlZJBAWt5XB?QAtk6p z;PZBUYmLv}O4#vA`t8Ta9W!j|LYfuO*R{kX~Gkj&k=x{OR zgyuxc7eyW4QKwM~Y;XaJ4k9|Rj;;=@E%@FF)P+@9Wx#6|HcbPs9Er>v%et4vJrx)Y z3O+mlAgaHtAg>Nf|0Z2za?+B6+hfpony5lDAE$d(o?L1}N0%V|tJR#e1J<;%&1W}W z4sdoDCj#!=VGrjHHMfK~!Aastb2s_g)o|qjTPwpxh%bS!912Ze_R1@tsT?0hUX>l= z0g~f3qq>IyyT|fEsc3UU%%e9f@6tYuSbu!PUgly3^o}%#>ptxjwWfP1pM1AwR0`_Q z%ul*q5UsD$nLPe0@(4Nfp56?GD!KCH8Cq7Ut-*bUr}KB^_liJCg=aP&2w@$IA|4wz z09gyWU?8N!5TMlMU;(rK)zk;6jObF@{cH>4aH;$*7AvDf@#!;Um?R*(8&!b z5TAj!VC4&7_>dCm<;$(+T{TeoPk0>2{Bi?uVfbTXN!yb(S#~8f2){1p713Ty*{jc_ zRf2HseOZT8+!fPXa&@%N3i994vCh!EtP(;}!4)kKE%-$Ir&(6wqjxugE|6~v?;rNi z^h=ZRn^;Nzm0U~}M7eO*=BYA-tWFv8ZnP1qe?Ete!mwVw)ZOGc|2qNyR1{vBFqdt9 zt8xG7xKiWPD||`~g42zB1A?)^}Kb zHZN&k&5<=QopZ~J#!ma`OZ1?J|EfUB-SQyjl4>N4fd(x7L!Tv?k{Xl|Zi zj!2NPdK#Lr$aN7wpAeRyx5Er=tJ$^W!M|(Z|tTlIzdC>lf3BIlUt5Nq<^Tm~-|%FF_W;5qeHfl!yrS z9V6$z>|&Do^kuvZw?FH)k}b0zXk(QJeS<=)fX#LP&{-( zR1mXZ<8?!2fYl{@0Ezi8RS2-g=bTa3d*Q&5p}B_RA`OEM>K{D%u@0Na==gQGyV{eE z-kFU(OR^Kv7pt2ORs?Lq@qv7IXi2vKqKf33 zR~4e`{tcY0mG_o&UQI&*yPiUi5dRcXr0|&)XZQi&;?5gVlgjsGONiCF!slVgk!>pJ ztZJM|yhmK~(d5AOK36q1cB9m~^hW}b?T;y(@{Wy2Pli96zt0DS-1xLeo%g87+w+(p z>nEs|=n}0MPb;Eh_?gkGvf)rv3^I(x!*_Q~yK^$LoJi7p0jnH_?F3AMe?u6qKfACz zxBXJe>2EQe*q$tu`?_BD9)1(HV@WigmKpH)8qa8vN?apP0c^wh78>C_RjVEiq^C_M ziLc~F=qyRnDrNWFk00VNCHidqC;&lO-YJo^ilZH&&-2-nnG7s%+mw0h_s~!K*O8R3 zdXceMp|+2$u<*a4dybOy{rsWgc1HcLhxIs2qQ3&MoFc#~p7=ka}> zSXC^xPkO?8?qUqhJM_C!S!&(m8G3Jwc`Rc0Lv(=16$e0NUMq zg&0AcMq)4ca){?MH15c7r++038WzbRm^di@BInT7Q-|RVTyl#F$ zN#cH-@iNC$)^ouQ!q6}$)J3U?09q+e;jv%7R-)S-Tg~Fv-s)g$Za{wkkBTK+0U;hs zJXGJte6PM&iTX!8$oZr`sB{db{2cefDoJ1AZ*D#m-oYZdmG{q?_rL4IK4v0^_kBK= z-j#xDpZt3e8`$7C&CK}3T!m8lU>~eN6kQ*41SgS%V5hKZw=j)Y0#FP)dY2(Th|uUH z*sKv>v8vZVEx?Sto1+TzzFaFnv5g#17WrL9fQ9+6OXt`vpdPYF5qWs`#godJitEns zqdqueW_c6LUNyQ!6e)bV(zIh${I@c-qB98Qqq!2VR${EvJCyR!=6RF<@y{hl_Qyl2 zRdh>gWyr&rj-TmBVa~l0g-EWuk#WqPgx0ure2V|klh;4=KQV%yBZ<&=`Hd`3vbOwb zM`EK7C~{MW#PqMwf&TJ@9#J1^mA=^L?)=LLp?z4} zz^fRs$dnB19)LxSBwkz09b)2&L~W|Jf5_!{@4+(syl>;jtxMRO)@!;>_C* zf|Li*srkh>E${4jGP6<;xw<_rokHRO<7G2pVd?P#keF5p9sPK4xZ#+U7-rMwnLkG= zQp}}lGrZ!*cZq-z186@_t{%;RgXMksAD(?aQ)6-CqZ=`L_M!Oh1Io|y@hP=8=Z;nE6WMYM!8hA-?f{1$b8cd%+$!rUIY(C?#tyd?@}8%cbPu%fuV zHmJ?qK(RGCn^1^sz0*lppm$UUzNT_2bypgib!{*TbgoE-8kMliGrE|*OR;L`nD~#8B-YU(wWNs_(+5Un**Ep zff5*To$NlVS%x59R8Luue(S12jXGt_L*fDL?dgaseG8>+IdO-~L@F|zkWY>U^Dh1x z0rk7Qi)kd!8?2c~1Fy)kWslqI^)fQSdt)j@1z`Z2M)M41OCzTRx}ZKg!ot(XDZH5;arI>LD3nB^1q++cv|OT~`i z8ZoAX%GydeBvt!>ee56IT-VRx%(otrPQUJ(00XuH?IE}$Y?tClldCSub+=SuqEB+D zkt!~vrgb*u#_nbS1i$a3D{OkQhQ9C*_ovEATl&}ISmP<2KAlQ_-Grxw;okhm`w5qK z$_!LEkAFQ2I`dNsF(z*}iya2}T2Gyy!JHg6a?(VNYQ-;G6|4Wf_7F}vyw!Qmqj_bZ z4>QdG;vN z=^|&NU-I7b*sajdJc@(!q=!6FXSTadlX49Q)nc-2%~l9^p=1bvHRosomH4qXkdb@k zwK%z;z?zgB&4?-P8#|sLzsT z%{Y;tU%0KwHCb3~$ktLakPPO$8i3d~dkjW@-}c&{roA_Xy008E#BLYgH~|6E5d|T5 z1-=~Mav%F2rjId+NmKW#&3}4tNTnvK&2WU!&Nh^Zcj&P(k)yJceJO~@ zoS%KO6uItbmOcCzhD!{lYhWV4@#fZO*oy7o-8*q#kz1lxvw;y#OF@^7UpH9N5Gr9D zYX;BMkr2>|+2vZuzwSUhgC&IIbE^sZG9UEj@$y~S&z<4_c`&!!@pbI=$YmMMAVTzP z!hhUsnCf~c_FROUC;_J{ehp==1oXfm^pPqb?6%TBxJWN{YB}-$xNgnc47!yy?)4~9 zW6^M%8DbP(-}y*_8Fcpo(^}Ga9~-mB)pA8)~?JOV4olI{h0(@B+Q$xC5d~le-8b& zY#`>{j%RNi=Y+3Q8JeK8lqc~AWDpn6ABE0bo)xBW^l5+iByDp*_AG z{a+ch7yxnh2-*Dy0ou!wH}(i)Tdy_C+LlrjNC}H6oR&W~t|{>)!iqZ@y6F z{Z9uEMXfon-58Px??G!D5oo{xn_qE58U8r<{UL@3iFJ7md=6aaM45`lyZE<6eG8P0 zM+Mung>esC$yKLmsfO4+x7~jV3cjMTb@*iwBQd_KiT~bVMD7G_Fp-i#3Ag3VvwvgJ zeDa^SDwA}O33bLZdDOqk{PT2>}^ZuiwC z;D=h{g{AxG60UoTEx_=y8X}RY`67bD=rAHwZ~`vs`Cl9+)W^D#c=^|MK^l0IzPS41 z>RH|V-K#!>g^OjYfWDh6G?-KFP~=n8*#jfad4nU}&x-_VP)ifu|NZ2NXLv%`xe)Rm zaN2*^Is&#*_a^vh`05^UOnY*g&NH5O**!7oW}4H9xfyUZnHgZ~0K+~v_b!(td%2#s zA|rICEg_#ru(Op_*H7m-p+vt=$fN zl0Qxne}1|j#4)x@(su-^ZXsUZ&0`U>#&wsB4sdxCkP>pfg9q8I)PzY^z-%`J?NJ5B#wAUF*E2Sh8%o4VuZNg zhn+rNdZLtMTj=$|uiVd*tJpT=#8*~vliD`09q3=`vI~SPiE2whwhMl##D7H+MK?>c z9qx91xPZQD#cTSpLwZk5pbp&Wau1%yZ&}IM+_TuhJ}t1BDZ>aUr;y5D*_dLM_>Nhu zW{83uG!i$muzqsesr7=fVVV|SlyYf&jCFxqiSH+5-I=A@KglOh93TnIQ06WWwkHLi z`0(;_E#OI;>y-BS` zRm|I);;aH=hTh%rn;-wey*2XFe+YF-UJX&cX5d(H!3o{=vw*t1xcbYe_}x`48RXm( z2qznisI9=Rd#nlMm0S%6sVZoNE5d{J7WmoU2tT+%aICh?!;F{08 zghazF>D0pG24#JQ)Ma6K)cNP>Qr8}e3zM4XO&dkAwC6^+Tqz0GK((Yks9PR52Y)ee zaK?{9Fh z1OzF{6Z6zi=_B4F_4tM&(p6ufcX59*0K|pS-EFRos`0#BxB7L5LxZ5_UPTdAX^u+4 zk$9hZ+`{9j{Wzi@62z>L9lE~Nu3YmmKinE@mFXWlux76q1Ml#$2J zy~IT%@vm!(DmvUe<1z?0uks9UEt46=ExfsnMMi5nUL=8;h@pbhLh_fZRqa!_-VAAd zZ4kcH@p+K$r|y5suWeCLiF|VN$gz@cGdn9NDaOHVBs;=*wIW}drsdk;6KY3lo`2{AI5+U$BDWJUFm)aqj6;(x(Lbi7|Yf6yphgBoS@~ z@&3jP+jYo3-s7Jh6Ll86nw__T=~6!L{6`!G;#on#%J<>gaa>pc!8nirBEEOvD83b2DkFGe}n&vL_Vt7~BYWb7J?oTY5-bIK) zp$Wj)JV^Tv$30cGG-B}zio@Xc`g9iODv@tv5F<*T9f*EXNsILj(&5p#`)vj&LmKE@ zJYK=(vAM@6xoIfSeNoq*%i(xKmjsrk_OgAueO~k`*L~Z7e zG3nQs*XWS(`E4m7!$u$_u$@tYTjlC(IjL@S==w_alVmiyuJ(^(Bk{5D*_u!pd?>(} z^uz1f=n5YEtRF!919q7GvVTZ946bY&zn`pou#&sWCoFn+UqEnf?{`r&uIVIm^~=t0jOnZog6W`^$>?)m1L z2WWq_QHkKRuh>q}4<3bzfY;F?HpDLG%OYwa7>9-nN+Ul$mb z)}d>ObXR{(Il?cG)(n0iFAyZ)9h^xvS4GnJ9BiMuw#9}|PnZ4``H#`sEItn+NY_H$ zMv-g$J)?uqt%56~B=5pwGp^d|uO2)V^?gePPWIHo$*p{ z6+>TaHo3+CrpMqvE_U%n%+Vyhm-mR_ATK2a?1MwQ%*mg=@YteVRT%l&W=yGK4z;hMYLiI-d7jH45`uo~Q7q7}y zfK7gF5dWbfX3pw)gOG;zXTO37mt-de`NkO^)!O{6<{4L)>i%1|53+~T9A(i`akJ^c zVFDALp43U8v>D_o9SpxwQi_`DP?%B&Ku-1){GRrlX=HAikQD)Me2ovR&?D%ca(EBy zc=&6#_LtuIsY!%%sA6fY@p~ziWhoQ=OCt;>AmG}gWuKyRHw+T%Zbbhx{2bgE2x;5! zB)Z951iOh|T-)vNQ3|j7e*I<$-p-u(XT(}{B8#*cX%1cNXeg+HS=?>T`tI0~hTw>N zhzHIt z-wJuuWFu!DV+jd3l5|wjKaQ|98RQ;JOz;H4ncj#z+^U` zrh{^b3RJ;17r6k%*gQr2UScJ8CD{Z1z(^5DtkdW}FR`S0=iBIWdp-)hfq8OYqaLfU z1j)d>Q8r|9uSww}e2xa&1zfFBm|-k`-&=jWhFe5At#mxI%{ zxjnzZQw#Kz8CyxCor{W>(GN?%*p)0Xv_PMTs$O2ZtL9|Ug4sOdsva*IZz%yyz6G$* z;-;YwJo=@9yjDSv?qfC`PdR~rF{7Wd);QPDwHYZ!7!Y7Gm~U! zPTv^s34I*{I?#&xv?sFNk?XNy@n%dg#LZ~za)Xn18G{%qTRd_Op)?D{3rivId@I6w zWO>o~SO{H*=eR5;{Z(3$xo3UK!SZcP9P99=JicQ3&^^Dw^?L%;Fj+G>Xe>|_dx)<~~ZxS{*H1P97@Za9mlfgC*wjU)~yV?`)M#>TrI1Q(tWCw*OwNV6^i5qdA5vX?j-LrqYfo7yX$8s?i zB&WcgzHzMi`pM*atDU{M*6tg4=^GUi0(f9>GJ;sxPN-fqYe^WAM3x@MzT=A*ViVp~YzR!-_9svJmMlBU;YuI& zB7T*I{Ix8mee5wL*+JO8dUtdMBbwX!t(~x2fO~qFx(8f*9Neeg4#bHB=YUKSmdzEziS6~iVSC^u(*farDs5R(tY^Xw6_y%; z^E>>!^z6x7;=2R?S(xHg#>*bjZ>y12AMNW>=vUWb> z{bfD^cEU>vj`kl$t;6MidWc4%E?U$wc+7wgbwC7g>^gFH1o2o@d(9PE>al6T6J;pAt)TKLm zG5w}$NZ@v)%JyIY?_6iiObOg2t$}0#g|R3~p0~x^h4LjU-918XT5Vz;XmRa@&Ycu3 z)(0M;zK)$F*|@oUcs1eSgQp#Fq&9Ykc^C_x)1XTA82F*U+S-Oo?Gl)RDsMpc70trd zg3{VgqdG=0Xlem!%O1q5_Fj|y<8stHbqkYdB(dUj%{tB8qLLJj^v^mPDp^~H?Yw_~ zkM}I-*RTA&g+nbnt+uww4yo;%)&wz0L)F6@1q$e>4xDKg-+Bjx9RRI7H`SOGIGhxG zD$V_3JanT!yi%WTyM-NfD8m|uru{+MME}-aT@wny`_(~~bd+yN1DR4@833DS?Yqm-|<5+gF7u)C>4f?f}&Xc{@vbRpcB?YG2!*^m1M)UieMh zw~N)&APr53HF6MxBukt?E$KQC zB6A}^=jseIY#R|bC#fB9q)U-tfj;U+X^&&GiiY3hT${ym`!k$>pSFA(8+*`kFHK2q zAzFTtdV4^C+7<0JROnyM>u0C_Dqx*`=y-KKDM-PGzwiTFX!XdJu=tEBfkT!=(Tl@2 zz!_e0q8m8?nYo!t_k9D{N*svv7bn9Y-9Y^K|9x=S6m#G$rc(wM0aXw+(%A(J6C`6S z+jY@&Q3v8v$9>(}aL&d)Mz+jc8?^qi8FJ|+3TS_^d-=vx zKFR8FKAp!#ex_PL&W?_3Fw~_S;9jSiqaVR=65uVF2ImC3+dre!&uGe7NGn>-_jI%g zj1)1_#*OVA*!_CK(Ido zaR)cL>XJ5VK%w3MpW!cuVY9{^!l)JzJDwr6Wt#I@(nF-1rw-P0a_b2_`=<8rYuS%R zn@fUwb*pJhgylPNKPBuoI=lT3=wNYD@S8PXU>Ng(7z5dny=~6v-k$-tPIftYNyJ>U z?xgCCsQddaz=^zurlg+=_-(qqp4(*B$J19*IALzYuZaQ`@11i_r(kQ$$XLPN?V5ul ztIh)9K-#Qb2YiJJQQ=e?GR;ixB86K%-GlKjt=0`kRqn(XMeM=VLhc}^&#Nrh!uS!Z z%=x8p;9w~NqLaz$`v-5wrJWwMoZfd%!M#ExN&m;a5sYxy|6BkR&5lBpR{mTh@@O&V_ar;XKeAZ*~?F4PEGzjal z(F_R1QT?90Le7%LUCR^%S*B;lk?&Xf}{r(5{mwO-Y zdtT=}pA~+SSKH!J@e;dPI{T-7&!;Mo) zhWCtZ*wr{k8#RuE|LSgxnf`TL;vhKSL}Fe|-fQT_#Hv^@r}wor1OAm;t{17?V|QkK!+JqCehFni7@_sOh_S3HiwgNHRV6>J%EwIQdXB>rIBo^_yCT zUx(?^>NTtUQtkCi*6#=vlTx4KDH0{p%lDMb9ehT3K$6PS-39q>{<>NR zm;Q?W6vAX|ck2|BQDgYMp<*klK(QoAYGrbq4=m$~a^5f-DqP;d0LZwv)>vdBEqUwF z?B35U0^_!80O1I<#q$a!MkU*&>y`J=Xe70qdF45 zLGzB#Blk3N57~M-L{F*;N60obdO(5`~06DL?qHL$^kx= zZ&>@B(*8Qimsl>B)(;P+#*q84%;u=Ek}`aI!aucI3mFLhzspI#YoT0@i0}~-nO3_E zDiu&ZT^j5Nw_7~R0Uc8X{;+!2{NSTvIC|ETwaxem?A9u;`||VXmc*7E#)F&*ATbHv zj?(kR-LL>|!!}D=?QFPEMFY&xYl<>o-kl9bfhoN-f55_9j3*M>KMa%&U+A6Q==?T8*J;%dbIRf-;pYA&M@X;-D*1i z7wouNogBnKFJa&IvY1vA|Np5K0%Y}@FW<8GM&%{p(haA776W?f?_Mv${1}+&Q zwqiY{_>6{XZd(sSnX*69BnIb?zu+cD?|-WnbeUiUiP=Cb7RpQ7%e7+5?s6eMIPGjU zMc(O&B1N##BW-b~)1~Ec+1X2sfFAAk)10mHJw|})SYZD6SK$eyt{$9OJ5RosaMzLJ z@qN0pgrW5!b4zH;U{o#0Oxkph2JD)ao%=C$+BD)s}q-aJI zRv_?_7i8^a!G8}&9D*%hrhKzbbt~5$gZ}tty!?XPp?@Ohg+sdgud6Z$evIBSgEkXT zFr1qTb2_M+kCX*=cE4qSxQO0Am%3QRI=FZmSq1WSmxnWwXg9UZ0pewPh_EQq!vT$B zr>S6+p;SF961n^rFJk%>Kj-21{K4c)iIG$o^~lR*fyyIkfmj4G*VJ3y?UlA;T)-*a zp=(PXBLDCBos+S9)o-U49|Q;`3cK>Etz7xJ!nSU!y1itzR) zcpaG+%B%9lU;Vz;WQ^FyHr(GW*FsyJg463D9G~_TC+so+tAqkWkS-!KHj40C#{`l* z@5g&wi85gFTWcxhtDn3UdjRJ}c5X`dE&Yc1j-vS8=yex>-1SUo&?YGzuD55o#H zqu;vsdRpMw`G`-_89A+FfdAZcJ#8dhXy?z`q?WOEW2f^zGR>T^p?i$2tA|TIzp;O|ZwINSoEoHpO z^E$(+rz@ycjUiyXPQaOd?C_wNPj;M@oP$EzWCn~|6`|sxu74>Hp}A~W7KefshCT8b zZY3YJ-}z8ieFhH&N5sk1=sqV?ZB@rFo&V9j>vNdAyGs^Q74Y-L^v3&7USa)(Vqo1c z*5zUw$Za=yStsg^)izn$fK4x%YT71W=E>mxKY;sf4vwrkY(SY|Fjp_e{IVOMcoOc4 zBYBhHpj_^?LjFoa*>utBiIsMyQ@V}ACt~Wz&p*Z=u2;$4=%K9uhU=K}T6fqD3qnt6 z_Ex4S8z@F5T&vv?+}y$Pn2+97bMc2P!)8rU9w8Cxm-=O^ca2HiO^SPZ^kHQ^N3RZ3 zn+W1i7W+E(TVr>>r?uQoQ+&+)4>A`&%0+8##oi0TZ_aEC^L|Y{j6LF*@&GQ_?5jab zrX%chQIWK&3O!ckoBz6*12;xW2*!MMe)utN14?lyz_flV^mn2PeyuvTZ{Pz~mkkIT zr1h;iH3P;wql4n|Ul-NJdh5LF(CquRW$szN&1zH7&!q73bRHo4>4p z_O*+feaIKIZv$l?2Gf&nBNkyB^&~l@1^Q3dG@yj|SgBE~sQi*olYapT+1;qP(E>bwc?=sSAhQrrN8%ey; zNyxa1bNH2;zzrQCM0=>y?ZDv?KUsMKm%@$IezQbo_@!-LrzN8t3G=a3T@0a zB$-^g`m+gnEBCoI_3mL7Ge;chmf}$BJqKzRDc}&e3`-1tvp#zpbex7`E>-kQ&?V5D zkWlr)w}l|sG0r8O`?1v#OT6>NiuRwlNoE}v9m?EtsD539S1<-JyAHOvGW(MOqtivR zUB4Q;sFYMLIFAKT=UC1#c(OsEMdN4}N(^Zq&Z8jZFUuikG9>Ico@N`*let@10Tl(Y zbC$~O7v0(M5vm4Z+oCkt{#_J(M)qFM`u(zL!U213*Zz$$hVRCbb0cVg#W#mI6)wKqz$W>3pn>%45liDw^ETFqD7 z546xl)PqV8>K3nyXIzRANr|LDRv#!*t^i_!J?iea6g7O!@%edv&-;)sX=PAuebbj` zqEpWYQty;ciJrz*|Kr#seFjl)C~TS#4Ih^8k$!_A#CeVY@@!>jZ)W&*(%Tsr zj}x5JkSy%X3G|Zv3HdEXj6+p>{_qyd{MmjZ&}@cJp*ncyy`D~b>q7W5c~WvGCw9fM zNaFDRu#5~pGjbzF*2{1>A|n}^zn6s)%u+y$fIS8t{yUziuPEmB=+Wsbg3aB z7EG(0D^^&jBrb;}6|ftWg^pzVYVDc%nzm8BlQE}zQ|mCG>KU!47Otu}X*KH-1R`I= z)4z;tRejDuKHRN1*B1fL1VwgZ1>nmmpSO?Uj~`49|M#bIj)$#W9C*c>`Gehk?07k3 z(78ie-MDA#y(o2*M|;+BX}7$By<(i*_Xa##+seuG+HG=eH~@&fcYSN5-FIlu17Y*E z2_$t8*(BR_X4rhuvp+MTs9+YP{dyvo@iNGa-Mj0JtCoB-U%~-nIqt-xB?*}=> z!Q#P-xyS<}D9beLe4L>Zi=$P4<WAFo; z1Ik5R)Fjxf^$CpT&ueiU_YIUm`pf}vDZx(8A?rVxK4=Z%cKEL`0Jb!>PqtJYjIaDU zKhpWjZNCpjXWg}=86)5t8vLDqA>N$7%Sv93V{7^s47ba;MVFoI!dtYzOY4lLLHraP z{Y=_C2O5OG>}6~fQ);n(y!*!8gOq}HM&!ixtpb$Ui+17W2$zX+P@)YbqD7#Z7Uli@ zrBaXv_3QPT8-_iLxvgY&SSEYQfAa%5S=n{6$~%?4+)tzrzwZw zT9oli5B}_tx8nw}EAYME$%7l6^~*guhP7_*+|&J@9zd?Oovw*1$7qxG=RtGV6y%}b6qBb!V$-MA|P^@|a`8a$7bdCBCyi!vY_bmgYLMRl- zC%-38_HuR~B;;GTrED8rcYHy6*lTVa5=s}rBqW=k4$G%54}G`g`D$(!UGVeLts>`b zX&YhX&u!-8X@r_$1o}hKG^WKrW+{s6UTu_zk{_)}+9&ZZBNJcpnF>HJ+NF+zPVTLe zC`gtFHJvxE2sR`!ej2t$xyiSg@JRH|BE{jX_t8Q(xkFmFyo|;i9QMH#1m1AM)~i*d zTIk_OMO#hM`sjLjqTltyON}R#ZZvArA>`cua+RDPrn%e+5=P(<;Ah-3Vz4Lp4N&LH zxFthC3Pd#R>3@5}O64(uVZdIEBcGWk?Am*;&Z*F>usHRkvBd0*jQpX1?*)E^vjYY= zYkft|Zv{4_FmNj5&HkCEYsu$5J_r{A>k~PO_(1dJ=7$%DC%FOgM1$sU>8Zo<+Fu~p z*Q=UeemyYo&W}*W8z@1xM?C8KxauaW<-h`Pe60YT8g1atirF9wY4CVa97`{%{wv=; z+1u@n&6OWdOYmOgoto`9nd0RuKd&>1RD4LX^hNVT`OKcfM`ZyXMh-4fLu=X}QIxi>8fhws)z>zwT2V&}Dp=ov zjwy#+!j2DK(OvKeb9YW=MOyD` zHn>&8`!8^(u#|n@{FCd6DQuAQf@-&t->L#BaUzQUxV@5`cr*+w1yMhf)*=x zoV}dHfw3C!V@7Bp$F7vZWsJ)HjZfH!C*S(Kb*aS}>Lp!YXOK!kJ0i_y`faDq(0{xD z2nKPgCy!f>tS;~fHvM>m#5OGT3{UYbx{Fk>IQ7+)$Du0qsu}JQUG(tfXy{piOu5-Z zkz?7d-zLm-Kx4tYk?-DXIZ15C5PGD`+vJw90ZrWZxLXgDeIEVWy`@oi_L45W?ta$< zBh=UUHB$jU0?W}v{okg+(3ZlKg*x%X zHC`?fE9u5v?B)a`JCmh5_IysX;t>_gig{wKP81wYO9{SBx$nUv9T}2xaDa9k!ka?4 z&DbUi4gv@;bRiJWVL>8jdxUYU;8Pfn1~cVN`R_?Xi*sJGfqsoCbiK(uHypUK1>z!A zzcac|az+3kG3G|YIh~iHUwuMQs#il7Q@XDR(`(c~9Ou#QwU7A)c>#D{mj$BI^UsQB z7xL;e-g|u2fw^<$3=5!k}S?Xg7AhdpF^JUM^F zOR=@eQ?P3G^fD@hAATp$c>}y|;(kFo=|N_TZQM!K*wUvt|5;ABU))UOa{#8T8=p!D_~U8%ME>V2Irm^m$HnxvYMmNC$e1*MOmbXBYvJt*bW`1 zZl%R~Z_QFf%3Y7re)wrsQgiulGeY6N<00;VjPvB;e+PpC|KLiUb1}b z`5L?bC0VV^IW?ALoblV0#V?F57jW(KJ=;y%-;bb&k6> z!0N^Gqu>83e#7WZ`$k6l-^*%8ft&a@uz!c;G_D;OsdUPuZW_44LXBQ__Q(5^QL|z` zWp=nMwRRArI5a*G1PRzqnKU?jGy=MOA_knp2fEImd2qC8-M1(B+qU9O?5FO@g~`q@ ziUEPRl!rvLu5hd`=J|ojU?xJ=48cAEcC|Hf09TKV^Gf?R((Vw{{i)&#Swe1@dF_ z8bF7y|FPH!Ep$bKrghtD#m02`dBkvBzdsx(W*XooPL!RJ!_^jDZTs&a*I7Gb9M)hs z+C!(PgGdydXSb=V;dd#1YTSeYb~XavtesuF`G()j_UAli_Q-qbh5glUxc|&{6hQ3r ziu39m5)Z6t@7`?stYxs<7WY~pqtLi#@IPZcv(q0}=kfO9b4hyKeyJRERpi3jWuj3Nkcbl$TzOQTl|+a_wH&*%phVtk^V1ad--#iLN77V8e-0e?YT^! zf-HP+q75i=@h@uR7aS)VE_}KBaxahk+X!O%uYwB^P94otejug)@7Z3Smk0BMn*B6v zpMV354hSh?c~e8_r?@Ejo{6}9f-5|!J>mlv-R*u)`J4n;0UmEd++l+HQ;B>mZ~mNFY%`>JuCWKvbnPFLrOAxRE)+Xt}yt4YA&DG`lK z`7y57u`AO?yx_);#vn&)v1!MO&1;9o=l0aOqYy5ZZ z1?$>YqV;%#ds``o!_hVxyXpE4JEWHC@kz#hhZ=;tt3%0+z@_d?|A=NJD&79wGWo%P z(%wYTgS3r(0p#bZS{*x`8XR_0`thirMoGNqs4H`L`5)xT!q;>7s9dL4xF;iAC0TT1 zfP|s#-gv}OAEIj?N;S^BZe_oQ_h$_6gddG{ndaFJ z{3p4o5Z?DIu-fPK8|mU4dE{&pq&$9x}{~okfwzMlJ+Tjnua5nC<(Ge85&_ z`64SI==z}c8cueu@#f|oSyG^N3$Z*1>-~;V3o7|LKNe0MKe6>STsPbFOuZRb!R}zz zcFz@_i*lB(^B|J6rrT@Ya8V-vq)2Z8opKVK%SxV@4qOB$aU7e~1|>Mrq)Wa2dn^4Y zm8tFab)!=tG_x3jYhEmbe+(G`QT}dF#Ib_W=%M`wM5y2}$XWzOR+r=3xSscSDy1VS zDMimsiD~n%qigf;X+yE6@gt_V4=(f55_A4Rmnnmf8;gu<3acYF1ky+6-Zngk4|cA2 zgyChD{@&=f@4)6atG(O8+w0Nk_yQW>Y0+t2cJu`UT%6RxzSLN`UK+No{D8}$MLe%5Z7xd$z7+H zq_va|EGiLjYcUH9xi5511H5|1&kfa(>s0t#1^eMm5GKyaD+bCw4xax^0m9a%1R|Dx zEd1+sv_CkVrIy+^Txtd5L(1wNn=$)c>tu4w8r|#J3dQK0&F{aK#t1+sat2(mH(;1Q z=zOg*e?=Bf-e6@4YPMFKD-$^Q3b89UL9_R&L9YmcuLzdv53gQJm9)qglViHSw&l#z+UO)(6kwwhneyUv$=c z4&H zwY{VMxu?@_;7*V#@Hh=vZCQaooPCl(v||t{?w>40S2k&S{SArw1YqczbymV#lKXp8 zO;TC^Am-wvjQs0`V5sUl1pWa6(N9_h5cXaCl0X|bH7VOGLpBu|aOXcb^mQZ7+-+O+ zWwZi4gZ&cX_w_olH|F?d*Hb|E#Gy?T0);5%b}ajZwBJS>ncnpO_Q~0L=a0qLSy%}6 zKkc>Y?byWMqTL(ATr`x@r>T2un1M1cX%EEnEFjYmBdkmmS(^Cx>j7!31XiitqVsOB znK0ILnxm(VD?VS(^6KJ7L{&UuPOlF8B2Xc6>l@8>FfMw~Uvb2lCe{AqC!Ooh5t5rw z?6#CBZdJhUx)B7p}ImJCvuH2<%YgQ3N zo3;Os4HJxYYtnS|nqq`9$%vK@+m|f!u`nE@_!nRDk6{iE<4Lln_nH_&dUJLNe^ zL;DS3P(xnN@w+W))Rb{=^V2_Wgn*P`Oc{ynf1NPseSdg(lk&Cq$u16Z{C6B}4U>3=a)uaH0tg_D4~#r!ql5;4_VtN_)sb_o6B0(t)Ip)X7Ov6~Dq6e|Fw zpYm&PP(C)k9UHm7pwz`QsMse}gOYyTPDS!=-)-zNft-h!2S@euiZm86!15SCeRqgi zAkLdX*>8Wb!fFq$uU!IE!FYLRwmBJy)UGoQI=ueX`R!K!#1H?To*UY^Ik_oELCR`bWUXv9zn_v)e@D^=;u0Ms9Y|P7MD&>*TsBrGq4f5OL)4i# za<~Qos`b*53M0X?HI$NQ_)#qByNegESw(?*Z%Redvh~ZU7g0#cDI!|kO^U&R=LX*= zTG+}T_B%aW@NOrL+x2`Bh@`rX5OjKM>X*evOD7%q`z6eZQ`95xMZO+mvc%^?7s2=+ z!->Ust<%q(IyNmoj7YCjk~I&ry+cA|ZVL@7r9>(`^UeL`qbxT7^y2LSD}RQfMNO`c z#C=y1FC}eK%I}%m?JBhm3KObP#m0}uF*F}I1WFWN=XPH!e-FF!W+ep-7Dv!#0PjVC zT><#uJsSup`*_0S$2BCogeM{au9gl!9Zx)o1ml%hpa0lQN{4Ix+Vz0K0`Mz6?3avC z>ly^H6DRA1-NqUA$~IB@9Y~D1zN!^nS|QBkxz*K$P5IuM>yqotF(dxh8LY3k$P~GC zJNQa~_+Jv;ALsBCMv{41_o~bJr1kzKu<+UsY#7$3PuDaIX$ljg1TP?&c8dun`b6f+fPmOfc3*voorAuD8!)ALz z9zmE=$M(#ucTl0&f)2S$r7i%;8K-AK7e{pAhX6C}_7JKR!Q>=*E zI>zmtr1{dOf&z64lKZJ(FOABJ;)6a+3FP~I1>%;DVV~|x*b@YHBXHT8xY8#0=_2|4#`FMq=gy>8??~k+8Sri<=(^<)lp~ z(x7CwP&6=LW~EkW(uA;#Ip)W4GFVCdNL+Q3??o6xP~>Ize#cgUbMRg&d~VEgZ>@8D zV(L#8Bhc`&8jhMSpM1rQNcvVm<^fNn(c$ZFC-Z^v6>d@A48ne63-!K&@ezQI0NjcM zIm4fR4GVL52{XdHDj*+Mi0hq&PoJWMUGxj7HFZVAh2mzd*24onvm)(=CwVs;vtHb! z8(Nivy(f5J`3QNSY_l+kQvB7(G}iQ}XWJw{Rh!dbV;UeCP(eyS67`9(AOJmjvm&>$ zlAFXdqog{#Zg&OlxK}*-bZC9|lgrsqFXM(dbfl$&EaITOcg2A1wRA9|>s;nH7B-A;3h7$0;GOCM$ke znTned0rm$g0EK;N zDLIeIf4j~~dU|lsmuP;r(3G|gn)sT}*`Ie{1`H*kkBYZo{Da0SjiJl}@#nQ4HCTB1 z*ev>vS@?e*4;J6$pUL4-F`U>sXSMh%;F!^83$qK*nu*H!Spn#m2K?M`f4VidAc z964PLdw}u+G{J)IihQ#->zC5Cz&0Sm4}6}{*YPi3uh?S!^rTi>QJdLk4=~-7{QmA} z4usypjbj8c)}WgdJTLz({aR44rW)!b=(}?l55%NpA?+XY-4xE%MgFjYyi~y_UIw_H z5f;U*%QgQZ#-w8p;=|WtO{BNd)`}++rUNwaSKbG&Uq?iAq6rm37QfK3Hf8u1>9F_H zlYwaAtw6VV1n%)D_54O9xasz%W13G#^IPnDh4W)$^XK&(Ev6=yoqx86hIr{(YcPjqnS0dIglTK*jWdpr!eLkr;J&p5gns&Hb zc`F#s{4_L?{o>36d(v#65)*xDXY-LoHT7<3=vBza)TTL!wa1d^=By(Cz%w;b;g1@kCc95U9Rn zzI~K%GFGB(eMqj~a2Qcv3U@wx$6heU2BCF-EJyNxnruGA;cvtJbL!tlfVM=#lN{#) z4NK}~@~oVa?IvH+2w=%!tB7+bc0Ee*R-HnwFCL5!!f)jKj##!_aB*J>ygA}LGXF%f zm=XTk={<~2?$JeLLi3HD@^Wr|%hso?!~gVcGA7=`l1|sItgZ>L3yXP8Nc+#4J6iXJ zsWA!cj3s*FHLRd{5VSdvK@CW8t@5YDi$txkKc5|{c6a>2`X01E~3MgRA3_ws31vt+DENJiEr8BW+} zv%`C)s0`sD&%b}}b6{5l48Ko^Zh%fS(lKeqLBrgy2^mt-T+2y*@(<3}+>2{?xG5DM zl;?E3zf_IlZYqD41VTr(;C)6-CQ6#s=#KRpn;D{z{zg3BuOx4NyF|>LU?^S$VXN>- zdX?KJMwNO6QJuj&m!|{tYVcod>XJWAmk%Qd<1UH3e z3yX0ru`B%}3b)_}wFbrGL}5hZ($ThKeV%>Ausf!PTlF-bto&kBN>u&Fn+@jK8Q`Bi zh>v(+Z<>M%m*Z3Mea=a?vKn_$s@RqKUf<~$?;eKRnQ9HnZ0sFa!>-JBuk4G?m90Ps zmS#h0s9c7=;?ab+m&LOS*PfgHK)>ZZrKfM|tgJ*70C&1t$SWOFxaPeaQZiW4^Ka8M zTEJtc2DL{C(F|^j5%Iss5ZM?>WSS1XfMRl7_RwT)BF8rWuaxl8t_;SO<7o*N-Q3X} zfEytr(d6EQpers`Lna?0+fgJ!GyPDmUu?q7{{@3EzvX(I)H{W9kwO+fW++hAtP7$`Y@-OyKm|JCJij8#Te4JE&w3oa+S1`XXN4^!2|7Wsq?~-;?vr=a7N|`_E-FE zEPE&={pK8g?mQ4v2GXJ{W&?+FOUA$Vj_rBh=H_%mg{v8p6!%D*2z3>!G*rJqni7A8z;wiCOhVZt;3!|9xfM-^RWFyi{)#7W_zr{q67dT1+DxI{BvNk%ok zo@Dd!DU`@dQZ}=Lr0kY3d;f{0EX&*+^g&uWFP%PCZJ1PlQ@G**JQmp`#Wh3Tu>ZwN zsXigqr9eOo7g?vBcP8B|Z22-m{hIlvsc-6xW4$@6{Fs z=eX>H3uwH*eUQjtLAm1cgY83?^BG#+@(*~RibD}UXfAp4(F4PvNukrBruIW22l-~v zd>6Bg56qE?YpbrcT%KPP%7Xz%WWjA;2O_ zzy0!a)Wkby1BaVnMdzVNz(TRWN9GO2E%WjB_8W|TxL|G(fjY<^1qm;4#Ci9(1a7}F z$qz(1QUUpOICJ_7R52-pMh6<93VAyj89U9(pc}4&nT?H~c#cy@ECDB_5||$G_#1L` z`{>zqRgXjx2+a!sQehS<8!*+oyt-=ESJU)=Xv_l{H-662Zj_NQfAV`Kmg?J*xPjXB z6ga{9RaE#UMt=Upy$J%3zq4<&r))&V=vd268jsvXDONCeRcq6{4k%0v>&7}vVvY8G zrvWEdqe^V9rEqzoiG%Z|1Rx}OsCtJL^u5-b8f}V4!P8EjDSpd-3-D_i`C4;P4pR7p zt4KrKxV^f#xB5dO!e>_%~x1xshps8f^f6`A1 zTP$J76FV&k@?A=>+lptg7~$S$;Mrzq?RJ+=nzCZ3rZwAtv>S7GQWA2m?tIcvk>WT_{TrDw+JD;PtZ$m!g7EYLiyx-oe z=3)h5oijW@*_^?OEaK!N=h~;WDdL9rviT=0aeU0oy-&fDO_Ol-!vOWFDpK-4KFHR6 z#Z;%K5Gn9ablk@?hF=p6Y7>TYFT~+}PG80Xu(hE6>)zt_H-B~&Q+&dPbeu=0McUr} z$ukJY2TB!Y+&+Ngh*a8R=j(J!rBt=cGIHTVi}xyHn9Iy#=yQj4-)8NxnMl?pP*%%| zCnc?1o9QvN`z4`zQ^r)`jb>JMRUX5=4y=zpl*Uq|TGZ17gu7oSa4_ql=LyWZB&{%i zV0|rDaygdKrEc*zDj6o8^W_nDyQ$uDBgKFd0SXY#{ZTDJ6M9loK!q~=z7T=Hx?dzh zm_#@H2s=}R>?8pu?3l+Ru5X&tVo<_0$cK>>7y$n|x=*F`Dr3SzeP0ZZ z(@N7Pw6(s}73u7Bz4l9;AC5kvUueD~vDG4!vZ5c9r^O)KN zAn0{r2(q$0=p2>DdGg_mOv-IT13Ev9cFsJx*$*fFb%#aw)XnVQbO#S=zy~*MhwY)jvcFvf|jPcZ%$FHf|o0N5lk7(0qZrGNHD?@@na2O-F zV>$x}+&H0tgn%LGbn4O&Iek@S^><|WIsoyx?#{11JnqKlIOm{_w_bl+G$A9IrUsiWgU3vh@d+TIWa}S(L+8$>>$^$Frv*N4q^1ZC^ zTY}4;1P?jawj$Z$KYzu&lub|2mcQ*gAz%sf5FWbJik5d^cI>>!ocPMp->1T>6PXZWh<7+ z%lLTajSwXwY5XvA+tCL28YY&^W7y~kWI-vjbHMYf(i zQ{4-7L=Wk$pbzGoefNMPmn2F+7QS6!lAID!LXO=$+YD6Z#G#1{Aid<-D_a9`xXMx4QI$7Q$r6eMcVaGxt!(Uv8QJcVl(dBX#_m%**6G=*M4z9ptE3%c=4X~fj?BfrFRI7fQ zXC2rX^LVjAySbJh!Ogh|z`L{ky^lH73F*n(7a4ot@Gq$z?+T_d!*d!u0<6YO$dawkN;1(go^0Fo2ffdmob*hx#)5N$(+N_T9 zKm`A&y^7Y+Mr|QqKG?I>KlaGw^6!7jCLx>aKWTfTMZ36kpq6p9jgGvsELP!AB#BF!)?Z6 ziHwYt!-vz0%dgb$6zDmHY>2`K`Y2sLjrfoDlSGkoVWq18JP^@X@DqX4?%`N@)bL*)5)V`W5u-@Ws6>w8h~w@iDAk~=Y&Dj+al}|F=3<~6 zf5izR$#$rhj`sE5YMGAnZt0Qg$#72BOt&JVl(LXYk@G&`kEZussaRJS3pms3_^lua zk}O7D5EdQN=0z1Vsu`En&P$sVZ&Z~ zuik`VN|eO&Db7)6YtB{?Ouh_2NaXCku*)j)jev!p7~a3(Z>g5I~{f4I?|d7 zWt>u6pM}H+J{Mc+8R=B~J%i?J(msew+X@XuD>f-qNv@B;`t{?upw5a#2Q_3xRbIo3 zL&y+sPi#q++PvA&MX2dwTX%6o>s$A%O-J@s&I+TIKDcwY-Si#JpyMnyE+d;ImUVjf z7oV~-0eXpPrfEzl}FPi=k8FEdXH|ARpw5J_+V_9vTtP#b35y z-F`r>nXm_b8S!_)(Z4xgP0`q3MV8oLJ%FFZNS#<$E#k3D%SIzeG&J5gk%ZZ4tbBcc z{S3a+vP(i!LVda6u=R2hX;_g`RLg5w6VX;eBB2!JyhFMNhj+7P^L>PcTAzebQG`=E zIGl~XzW5!1sf_+_>yi_%0bITNZ4#FlEbvKZsM~aq;m+o@z*@iM(bJdOdH0yZ>(|HW z{O{iqMm~`4u4hZ^5zxr>g<)URP_!;*&2~`4QPBNIG!5y~4Y@KHkOxO0^{TyqSZ&ri zh+m`#w!eUO*k2Nl6L4vpAP&X!U^Wf}(}Kz%>@{ge!}^~(-@!m_;;lID43G(S zmMc7-3+4RkO_d4+Gx5f#R-6^Sgg?BWo+#}z_!hmUY6y}~Bb|gE?`~)Ncj*lF zxm~F{8QZkI#ynizt0&GOr3J(}{8!NjeJFxG+nTDl{j&V%&?{!Y}a4 z-k=?%dL%~3X|3!Ujizd0W49PgiW@dx&<&#sMhU;gwznSSmAL~oaagI^4iJ_vZf^ZZ zsR0fNiWz>Db3GTbD&9y4I5pbR11{945~N_e8*j5t?oZva8-QS^LzL=H(f5#6=K}I2 ztzfJQ5;F7qR&6kT+_XISl_s1wWe`W!56|(zm_*%I@9z`)h5E=Nkn#DVYOdSj>~#@xg1do>VbZ3I&YPiX=G zsF3stE0q~1#!aADQwS@(`{X?%sFXa~U?8wU)0t)5N)?%+FT3YI9uz<^C?oak4+>pK zta-`Z!I7VJ6sgs_`A%m877UL*aw2|-BgADd8Ie@6qVTI&um?2X=y#4@YlUDj zNdUPKY@qT<86Qy2H?f){XVWtPDqj4Mk2STiQn>SRX5NzXpVV`uOR2Mv(A9vXiL9gKK&|P}GAM=|0^Aas_|a1xvpUdfwD!d|-FEB;lV|Fpu7>qR}qU$cKyILbUUp>{m5#j-_t zX!@`9!3)7e?1)FmT>xHZZ1KO560#`|moyt<&P5o}n_P8n=y)8xj+z&~H6iw$M+fzA zd(4!_%^U~?;a1v`KQX)tRl2PipwR<5lp}Rh*S7BtkZ4Hwp`uPKg^p9sdqtj zL(-LK9GOj7v+8(m3c*Kv`eXHq{Pw%}K6nY2SLxk3=<2rn;toGa&HB?Xqy0yveNuMd z`0^}zC`rQ*sAA`mNlEUT`BV8wF?3=$Ofh2<1@J--CF9(bjP4w8-39tdO=lK6;Zhtr zc+$o-)Nbzq&C^Or!x( z8A*)EpHX`0UDyRat$#0i{`QqD`Zv;4ix4$&O_J3OxABRpnF~06X=-K{Wc;)(bbR^K zzl}s1h+jIw9~_r}u_}l4+IBC)hNh;9V~$%S)6F;~iUV=&{M4g>9+@bf!G?uf*(^w0 zhGN=>#};(&jw>mE;1q$5z-7^^DCpeZ+tMPPDy!4&pMTmERlA_#U~|M#0S#tZPD$qz z6BrvLt@%(Y1&05;su^M?G7)l&p|KS?6w&Etwkz7{N^7Ti>3scv6`hGc6aF8^UBx#_ zCCa&!tCF))WGh1CsN99g8Oa>EXH#TuIYx+8lB-C`S(|(A$z6`wm}_E(W7Ce`exJYL z^LTtd@AvC?uC}?z!xkmbYed%L7^70p18+^m_q(UM#nKW%-OT>n+Bb+l zSqH8|`QAur+(M-);uX>tGc|kis&JCVLCiFTcIM*wLY%(W#b3b1A(PkVD65)K756nZ zU!1QDD_T(#ojel4xaZ=|lnA2wdcIZqO_-UrL~QZFOjIuJ=a4CWL+<4QMr#Lb=G>r} za}UK&8?CNGz1K^f!ekRokg5?WhAa*EQLe@kU$}BRBle zl~PIZkT17oV7f;I@M%24qOn&T#%ZhjPw0jl$xH3&1x5sALWow&=#7V%$|iVNEQO5p z4LqBiwQ&839J^6njLC@)M&JB)*hQr1dF<4ckKyN~1foa7T)D+A&o$9&94Y+h*=~x@ z%Hks#N{-F*wd0&ON;QE|2u(KiE8yby>4YE5&N$D|BXF_KlYo55o*(+2bx2|I4LB~^ z?5FKhc*p7S1e)v6Uy3V~x&nX&>BuW0ARwK5fJL9vPRPjbRbE|Ra*&*Ts-Ylh8sI^X zr9a8Sjk^6c^+DjZt=6CSeiMAPb}$oR6K{YWK2Q-qOU-;B4YhktnZHXPgXvpBeN^)^5%}xrU_rdc%d33*q;Y20HZM&X0bm zJO(=|)FlC&4kyHGrYO&qQ%GkcSR^c`9UIE@a&8g&rXT?Mm70nBFOpIC4Ila78t!Lrq{E!Q#_v*6R__?`ZP-ZeUz8`VfE{dGtsw#QMg;-0?0H%LxEK6Nt`L@w4?%v%Y=A~fpKd# zF@^&oS2_Jc#&&4l{aSvq-Yq({;}!Vx^8NV;pkgF#kiD8YREuKq*yTFv_#>$uRW=pU zjs6ku^j~5Z2{|^MN+M$%cg{<&9V`Gw60eyyf>9JT0q{M?J44f}8|zzX2BOWQU#jjZ zB|5_0pjSU-kG*~F#e#VC+6^e^FkE`V45_yi3TkvcnDI|#e4*6e*=pr$npT26OV;; zGS?{NSCyn1Zh!e;`expBc6$a~E;o63zh|YEaX{ixwL5FU_#t}BhAE>7bSv29=Dj6t z#O$Y|?9BgL2aqJR{Z~TWnY*W5sv;Rr4=TSMHuwnM;ST5jsN-2%ddJWIu+8{Bk$6S^ z5_Y#~rQQcf)|MCnZ{8HVUtRBU*uDLrdr@Skvl<@YL9;w=DwlVJ#;CqnPrzc2NtsoP zH=GQacFI{CS`dc6i8?w`Z2B3h_r=R=Z7eD8Umwa?I^W0M(72{;AX9NroIOx$J-avr z3D}0M39HmE%>&R&Mc|d$V{B3QMxV$WQPtcb`ZMSJ7MmfF18xNsRAHPfp3b*p7&*Ro zMN}7QMXfURQxwV$TNL>GLRc?+i3~Smjo99t80Ffn=MMKZ?9VnWTd&dYhy66ayIFY) z+=%5P4WG-Q<=}k^1N;BAtI|${GL#rSkb4uTFedDTJp78JN;b}Xy?!$ z_8rsf9Kt?ghHm#EMGY=|eHL8EIYn*925V#!w_+K(KezLZrq>}Svl%M|e_ z+2yZ3ak4Z&d?KjQzauYB0|ef0?|ty<4moc5Tf|7N(zpN9SdDl8@N!qF90VGQ8|yzK zd5hPFE@AOHJZ|{*q-aV$)O3-j2}|31_uf75-w$4bQpzvzCbi4iMtC^7Cn=>Gy!^#G z4^aK8RPL=auT;#@St{gdl%cUWXl^4!VG*@5_VMXn?=@RJ$zl=xNH4wcovlDccc#*8 zb=#*nMKzMh(w=y?!DqN7uR^Wp8S7;63ZEIv+S6(ZO{IQ8DV^D}jwueTTtE$N;LufxV^OO+#+psO~ocX-5I93%G6mctSgcFPGgxBzwLYI5NM1w_~nX{A%- zQ~=hgA4ezp@&>B)N8%dXPMo`!EA+VX8YxrY?LyLm5k|R7Q;J&c%a8+He}}Y*d+7ot z3jm=ZNO5QRf+MK_3&U9h!ZqQu;(&A7wl}{Fe^n91bm|caHnK^A4akvWjmIw- zR>sehuo(GwESIH_SFPuRA`b^K7W5VJZ6cUi4e!X-WiK9hBCHFF|Gk=*bQOK?{Dr{p#W(XqZOk*8qrS>u z=a;5ZQ9DH_5r&de032c*a?-p7T6f`b9elxdonok5a6mu#RJd4)vgSlZ`Td=nHyxP6 z*_#KuQqrJ9kiH}ES)RHw@yeYEJ7g!A+;4LN%5mv9^=Z?Qv+d7V7Q-ABzB_zFrRR$XL;n*&xnB?%ty0QwqX8=6`=H97Add5 zgEhoA+cZXOo_Rr4E#}}EZGF>C2PRo{4Zu~+J1M_6 z+B|+8Jhpp248{tsGq3Y>pI)@V>; zn&kyfS7nZdJPeDd1v%9~SaTIr=2<`o!O@uM!(F0RBCM#=>0R=5Nm;rzvuj5^YidNF zR``BOU+00>{Eb!e!mcB5>#Gp68Od{|L5Z^aqVUT<8SabV_M>tJuJE)WP7dbDL1ONc zVrhMivCHag8PMlW$Tz(z4(CqBszunvuvkSD?%TVrM2XFYhbQI!`?&Yd(^WH7>d)!< z{nN-d#(qJd$V1mT9cFja#ZgNe&LIl$?+Nu#BM8v!;>SfU5iv=uhBI!-aZ>>^(A&U$ zHh&XKymV0>zYo?0R)&CSuY~j#cxv) zI9T@!Jw=tz?c=Szwvt53?o_uPjImq+t2~L48}ewuEXCV%0ZgRBE|^l}vZI2)d7pXt z9%rO;7gnwd%f3oGaOd1+fcc5Zrpv-tC#><20gn{Or+$3Vv9rF|j1_?Aeg#6WO!RUd z>+nUWHMda35L=2@S%G)_nl!mh|FWTrHisA%6RK}J9SMXYVkR`s?l1D*oumUChlgSr z87&u&&8+F6UA5d9`kmOKK4Fxd^77`nwmOcJN2~vKy6J}4bbl4Q!#8;XVdJMp1;!H= zlbbX&P^%=tQ4^8*7-?N+G<}NRJyp>=+Yxm8r}NQ1cdRf-kaajIMtE*W9u%mj1bZCV58=2k zE_ORNGYs`vC#>wgbSV_ZlOPO&UMj~%5e<1LsXu|*=|qfOymXIPRHu7kQn?H?J*Fo6 zmF2{h2I}8NlEo4;4THSQ}dFv3UkI?<)NqdlxK@_#9ti2PrKLi%2 zaO*zEQiWN>(O=fO{uF#=(YIAyJrwNVslH3hQFi<*pKE7?MU1TBV%)U$E=R=V#n_m; z$i7*Vo}QqVOJ&#Mqk0TY7cUxfzg6OyLa*}UQc+A{e2C*w$h}KiFY)>QB#VSZ0wrgG z;>i+3J!SO(9#C%Qsi1E0A@JdR1W^P17T2A|*;3Fq=H1s52*~M|OZ(}ydlZ}ZUZn!` z5F5&xsid-4*m*Dz*lieL8WJg{6>kIlYlr4|@DMluPQzK2;5~`H8=nWtH&5}3OYWSj zXc4BFp+z&`D-p&{s;a*Z=rnB`IFBnk*MjD0FDg4@aQrdWGAYjj9$1Xu#pNiawx%+) z72r+Tv>&Yk$i)z9x(hlQ#QY&iLNk$Yy8Sn(l3m!Q(sqC6`s=g>beQXeXvB+Hbrdoc zyhm8{^D5Oj=PN^d=DrcE*LJDq&uc=fKJI(oYW`r{fJ=>s2MR9uZlp^l4#0C(w0qF<3R$nCK;ldd{ zlP=_V)gQ@d$EF&IRls|+6<}&70V>5YYmGBL32tu#`!&IjD+D-&05g~7bGQ$KOJfDc zz8}HR6%D6Wr-G<6Uwokb@(9NkYE%+;wik0!TSQdQ#MhSg8)WcVvb-kZgMR+EvtTx1 z=rU{5g=y$Us(m=sX>%UkT1^6TY(_HB6u~&HRp5ma;R4gfg9}kWj_h{A;>E+bznO;% z#LOz0{rRc%?ug%?91W~E6kU59#om^aM_;y)&mEXhS=KEZn{TaP?0=ZA`9y2flXk#B zWqmjV&|1>$Z?#XbEEF{V#h&B~BzQm0J!{M5PC!fX(0X_6UZ^IDa#t}F;4Zx5N;GQ` z-sXCBVR*&*N}_rZ$^}e|GWszC51zdRwJF`z9yDVT=^BEni%HT(76@%nv`2lO>kn=a z$tBk=3=Xx|XfnSCEK?Q*b+x^=j#{i?E|>c6NQhvHwRZ`)%&WcK{l0~<6CZL_ zBDeE#$JH3kt2Tpk;HpLYj%ui78J$s@f|>wxB; zV!n?%v@;e4kNmEKwod3BDn)&KN^wls}WE98?}`ogG~W7%*AbR-Xt7jhfh z#SZhfOyVPYs*AqSg?BQvajV2uHQmw_{XMbau*^&<$fJ#GM&Gowk*KWJdT3@}`F$qY zcOShO9^A252-M?~mBO|gXFI1FPtUyP5C={U zr9)lL_vbJvs)8-94qU%-fy3#QN2&nm3n$?cc0y&!gBLDfXy(T+|FG1R`FXi%WAxnH z-aknn@`?cS^&nt4KM}uRBU7;Fgr;uyJwXAIKY9HzOt^lVi;7`_E{&aB;uZgUdwm>}*NAV4eKUxa}N8$*BzCE}DS3MX>>eMm>eeYEy}#QXlt zX#Y-;I-odap3l4-13llvCJ6FP44l!i>s?B~Xxth_72%pV(}+y!p$8nGsyIz>sXE`2 zsbL=P%ssO1GLXRL!nVO7BZ;|V{eENNehua4>#T#1Y}!^B29^U%9z1yvkl#LhMGTZa z&rz0ARdx~F6zstom)bLkc4{6DbXh85}FxVEdkLi z$&Z_E!$W6Nxa})i>;>^%qF}fFbfT6#5720~gTxR{yR|%7m?!hX+T4Sf1Kb1Lvzc>& zfKX6;q)Bgq!#E9#{s2!dhkM7NyedKEh~fb~Y;y2Jx5a?)h*+zb_a6hV*c)x`;Q1#w z3xJ56(Thc9qEygNA%C!{`z+OlzSo;v0G3r3-5A8zt)@26_A}r>sl1)8n1%x_X+x?CwjqDxeM_(>kwQ?t zckV}7=1c^~J^588R}Yp}4M4jApk6l1qYv;FWwW93p6V})%ixtad8WyhYqet~1Gze~ z-tyxnHlIp#r#^oN1g}D_%%=DS%RY)@-3r~NPw+$kWIO+!f&R0I?>bH;3d468s({1B zXr@3jzvZZlCd}va-txmQ#mS?*+%=J;8yQy+ODkHXNTM4f38%IZ)hKKzkGPv^6r~^`$$~7=Cv38mE@XnbOb-2psK<3!<4&L|O{_KdwXGc%4-3eqSPFI>e zbKSrNYy76<*wnj%8JhrK%_RWj$LnccB>%+M*IQ(rY37Dw&lvoZNQ}~|Fkps(^Ouy- zc0*+%G#^z<8yYAdf?f6s@t#^S=KAKrhoZQ5GEN}DC%iOuZX*XDXp}u@u0xsYxW_ouBxwM}`0H_=wyA| zE8)_i>OKbmw$;eho9to8`su9p#>P@i{m>v!HYrMx`by5{s2fgqV%IN2u``G2{;S#} z7(C_JHL#g4!TVKzH-;cqyTWYUbYJYD51;o&OW{neeF^8u{&=>3MOrA~?FdpJV zSYd`@e7yIF=r>t}q62JMgr{OifCEZ+OqL@U0qnPCM~vzAVAWSinbTGsoAj%8aAv*o zuWD3^SdZJGJp`)nD#ZmjSqj)I^?gr($f>AJ$#J))lJ(;mu}!}FFX04CDff;uyZT$@ z44yzaWcc(;REg2B-keS7+|){0hao1Ky6u~P!(lZL$EGcIp3i^I>#mUn%_C6l5a^P! z>!#Rsp#cEt6KG$x)xQV)s9bQ9Udl5Q!j2ysPa78L&HdLqdHuyUL@dr}NJnn_or0#u z)ho3h3FLS-gf8mRizhfvtzM0;@IyPk-^a6h9oP}I+0o=6~N{Rb6BX3y4 z5iV4cW^ZW|en}IQMT+TnetP+OC=>YD9ENf2e>0Cg{8J!oHPOl6dW}=^aM*Unss)1+rbRF+Sba7% zS^dsY{r8^f?G9m8-(u)oUlX_hU>wvBfuHDZcJ$scFzxx_sGe>&>$_MnNuJCsS&yi* z?S#{Ys<=ZKzX4zFL(&!$TFy;eGq<}lHtC1pKHZ{AsJ|Suh|q}G&Hj5`YQ6kg>-TLH z@Kyi8(;^duC=6+%3mPF4l)6`@ir!|39??Zz7I ztV%vhgYW=#7VO2Wemv>Gq}*g@;q;+w3>`V;kYxK;6FPKtq`3YYe^ONz(}&E_>Aq4d zi=*$Z4@FD3K~IDg#yC21E&p50#uK=4t=!6S^zF}6jtF|OY2C#@@z}oC8anXk#M0LC zd+<`)JID$k59QE^GI&PGf^LN=Mk)-?G zAp#plve>m9P|9#iZEcyjfDFB2Y_A!F^9a*j3Pm!I-(LKYNI0 A4*&oF literal 0 HcmV?d00001 diff --git a/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/media/foreground.png b/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 GIT binary patch literal 12430 zcmeHuS6EX)+pUO#NL3(IK|}&d7YKwF5CM@UBE5tjTBw4Q5KwvxB2pw25vBJIB27p@ zOaSQt5eZd#CxmkF|4+F-=Q)?(#XNgvmzlk1)~tDFz3+~Fs;5bRo%8yoOPA=i9zS|^ z=@P~5f9V?4rAwDs!Yjfq4p(5Rx~i8hRVUG&*j~LT%Q>2AIqB+Nx_^yhg70E+c&i!%2~zqE0}mxIX= zz1$7|sWj&3yL#7D|4uLjQqV+x(Rz4WC{A9|^m@1A6`BNi38Cf3B^aJyqxF{TjS&2q=3$BC zB1Fu04C;%o9V_Yg;Ed;xpmge>%b<|5q52W_pTd9o;Qty2mQ+-Peu)^(K)RH^d5byH z>AGB-I7$|~9l)J0H_LPDsUUL#brIHpjO1>dJ9@_5&W zLV)s!AVn7*Hy{o<1zLA_Ky-TWzJ_^1=W=Gfyc#1ssqeY_2ww>;ANX%JT)(9uNHOtU zeqU2_{Wu6pLvCMBLgy+dx=13ZG-+cMrBf;#8KezD^}_F2x>_Nob0^iXEv>aML;8RQ@@sN(#bq~VsOa>) zW9RDe#_!zLkj)PyQ<05AjbPk5yJ^|B6q=sMX2L0JE|(P%=v2$6+4QL)cu$c*yt`EC z?)p#@xE12zK?QF2u^(xb0>KieYWS%DH`?=eOiFd!6)WRmCo6Joq6}7e=Nl_;oNJ{1 zu&szm^c0s*wAxfHSlk^+hb)aB<&B?9+_YvxC1LEy$(dDJ8J)d!>rwz?q zGTpJ5&uVwR#t4%B`T{*~RAd_Unnf&`*9c^zbZfsVc;v*@=BHOCX7VbyhnS5G*Pik} z@`U!W&dq$A-&GCYAWg@rG3W6ANL_2a)|;&HJSig{zyfyO87W{;ej&@-)yx~eu|G6S zO)U5U?QD)!ey@XcxEKX?m{R4VZN!*V9gT}6_lv@YD^}}y4OM(*#%kMMBij<9x4*by zCkGRQ3vqoZ)HvQ4oY~=kh{c09u`@Lzqk8)3R+$+hcYuhqajQqgq8qWy8X_QMy@1+T z0&yU)D$XzuW+GZpAB%%|^3*{x!r`8nOWhu6>t(2mvERH# zwD(@F(UyHL)A@d0q#?|SOaIrK7`~^_KhtD69y6E{G70hSpvkOuvhEmR1(|2efAmi@Xw9*}m%vZb>kVqe?t6*aL%179k2-;CD<(T2&{-rQ;%g&4b= zStwf@&UH8&T6lBt>jybuLy}~>HTF7(kmQuR6(8*l&xSQq79o~y=t@1Z0aSiA&-LWp z0NQ{@*q$n1m#1Z}?sFj0=6jxX!@eHh_D<=qD}vOG`kCQ^44In=iDu`srXYt8{4c&) z7G9;S9(*ydG({X#u#N%3l}&Yaq*lzrY-E%htNRQTrjCrX1NMi~a!soU$|=0*dXokbDxSFnm6OHLV@%5(K&ZQB%e+ZFne-TrP|veCOrVj;0pG zdbMMl{Z%MBfVA6b>SKLi zXyRQXFc}Krl(owbvDh?Um&9l0#P)rbdiZxK)8=RY8XvSG1@0=@vGxtW|3E{`T&9Zk zC0==A6=d?8`t>?}z3d12SZ$YU4KZHQPf~|w zJD7n^6bjSS+&0Kq6nxhj*9}9qDZC~A`nzEz{<+9lxx)v#qaCsGWko<{ahFVncU-R|715> z33|Jp;8Iq?Z)NXe;h$K{z8#lRB#JC*XUod!9+#hCfkg#-^FD5Jq@>Dt!SzYr@q0(& z;I!1>qg(PU*HMX7>G-#T5V;IOw~4L@XQ&5le>B4Va!sx0P1pm1PMa!%L##WB{CukUKwQLR#mw_r{d1DneIIJT(j#O#-det^FD zbdwZ-8R%84+Bo+g5iyd(a6x;*5F0xuclibP*ff{7PNPESiBNJu^Q2?h!4}38?XKcb z1cb%?RlBpM10D9~`7(D`#uzQxY}K)shcU_}%#WJZ`~FU)C1j&^b5i=Wc7uJW8^-NB z(rs3^Wms@#S~)+us~_(~uocjV^vU^euJHB^upc~CY%6gqBXHR3{FJ}D^V0uB8xrdo z%j>^}CvVUV6jaGJf5i$e;gXng&>{)uK?nWhEUaVrv+x8njtfCz>cqP8uUTn1`McQ;CD+jm zGle#Cefq~0!!v@W2XnNsA~8j@Gaaj+fT)QzP<&gR$L=bGEJ8^z*tHxS)sZ=vZPV!4 zw*)4rK3To_7<;de8PvEPu4Q5d;D=g00$bPnaG|sEP6(kDsxwc2+y=l@=8Gy3^DW?X z$=3@Y|B6^8mUadWxX-6z(Oh@9|3%Nv*Hz=bA3)}AiK3MrA@eOvp)YSd(Nf|v;6dz-v zI5xYnKImXz)PTM}jxK=GJh_OrE2HXqKgh*KB!U~;4W!DpXN6A98^kNt%~i7+I+`g5 zW}~Qod0A;Lw*Q@m73+!Rfuir!WXqcTd5mXE^DWV3AUSVk>5EA&b6Svd&!yh*!z+6( zh^>CvoV~2?y`UJ#Jho<+PlUEw=Y?Hyd8C#Oj$c!5d!Du*w4OQ9G&OxhDmQ=)tzD()srM-?#=f>aw-$x}3Z?qLOIJ{gnZu zd`Y3Pu@-6CD7)$*a6189&`vfy%c7^DmCj90Mw>5FgU_yh15-*dsMPOLpn%G&Gbq@c z)NN;i4jF!g3-}@w-}i(YUbp4WY;xYi8`sa3ep2V_UXf_!7A{;Fhp25CGF=6{xLd&d z!Mvrklt74KI=0hsCRMYBXM0Z?v1sDfN=Y&W2dW!hUyqiiU@A}R-XCxbIudes32?<&DQ!Hr>qn`aYQ?jSq?4X|x(CCDAB;b=wcWVCH1CfwqU1di z!|LlwpE@R5*{9XlM;`OM$(VZBN$c{`%$ZT3S3aYJwVO}kw)@4_EyP4SXgXkd)Q z7PtWeexnE98(N{TMKt-aG+YpQs`a~e_Y;}upm;CRXlTWI->sMI?cj%D`$7K@mQ<-e z6c3=23v>}kQ!+Z{G2&KQ99s+el!e053~lQJc`8%`$;xt_RQ&16M-jjl$HK)VZG-0esPL)%m(*xgTxhvj>YKkE?dOv3G%g-W9;dgR&pG1FoW|wrm7v|b_Y-VU zKV&S7NcSkHSjm4nrPIy#Wvwp8(lbN>^x7o60ICQ5m?QwOuUY9q(q~<6`0+a7 z_`Zhdli4>YUiT%XT1&z74m|S7pZ;||I*2@$Zd5=|9{V~xFLGS|sAE`ZQ=toXwPUzSz%(Ar!@#M}4%I2r*Ca<9 ze?7@cjo0^QC6zocYls~PXjm{I-w|^|?Hpmvl_!6;&?vERiS^(A2e-)2qxQ#IfuJ_M zgEhyUo8K;fE}w8OE$6nq26w$M-YgMyeYnhwguXF-@5ca=0xYn%I)Rl=_lZaUn5tgl zq{GPw`_E=ilA8s)Jy=%ks{*^ijmr0SqHYg5D%zYfzlqy~#fp6GHI7wm_SN!mo*B=(4jED535Cy$0WQgpMk_!VjQ zhjwgVnse1csNUVP_rkF)3q*bk`=D| zRm=kyT3qxBA7a}d4b433h)JR1r_zBVy6)DMRyM?5%=@^}YMnjurETi?w8)8Y2lox+B2Mc9(WcW709kmg&QO^PydT;QZ_K7tmYO8aA8M?Y);N zSn^>S4^jpy!tF}ZAn_;hcCNY$eyakky`&>*Nh{Yf8H17GR#{9&%f^ps6IAlo`0a7| z-5WT~hwWze!uONxb4D$Was0UyM#f|Al`@rMWg(+oyWOL{(2>P6$`ht&d;q3uD6W+D zQQKN!nzWpx$Ya8CUKa3dgn={(ad!Lm7qDcu`SB#dKHvAM#GW}Z>EZmS6yG22dWcVi zef}3H%>*xQE6XidovM|h{PD;~31ijm0ia9g=-tnlFk!0PDn12luSSt7gWP{nbUK-G z_;*xp66cFpR2OkYg+1wGZF$3SCHuNOh~T{QxmE}&DI?a%s+Q&BqRkJ^37TgbKmAKA z-lXW9)FAv@J#Z=C2lSk4@W5q7S0~BpAs>m(p{^)b2MCFka=_0~yTtPvSKJEH%6&GW zKv;f{iTBYXA0^wmTAmssRXI(3556s-FYRfgXSs2F7D?)Muw3X(n96>Fe~#_y!;5dQ zdOQ?Kp<{m8r8ee4PPIETr3Sr=L{BgNp=Hl~>nSiYS!vY-rs7>zJE&K9>k00!&bs>P zD`CMT*(GNFuh#^fdZE?R`V};&3K^rq3z5UT^^KE~V+Yq@nxU<{+Ug^t(FEIk@f~5* zgnEN(6_Zcdmg55!i|T1Xn2NBcinnnFghvgYxT5oG<#r&$ky|k5SaFs(+Vr@W6W!wc zhr8=;xACvw0kVQ6m+uK@w0M_|3*`l1D1SbQ1B%k-HMIa!=~kGkCfuQ8^C^ZQ&7xn%?zUs@ zJv~f?$}gE-(aEgrt|vKx z;}Q@0S-w8jTszP4_+Em>MvCg@+IT%eNk_MIr)gA`;*lhuP%vm}{=>pIah-$r^3{Da zp;l8BZIY#N3v`sN%POMh>Q=e-o^BM2OK_7-ztamrbZ{m49XWXIgg1Gqa+C!XfX?gxVvl@Yc z?lm`jKKariU3($HdVP4LPtp4+4mV=+tw*rjI~_q%R6DfIW|6`<`}My)W_VK!6c^i* zIvi5RI=c%+#{fOc1^%pnKBkmGk{n2 zC<)woa7^dmGd|$2v77jNVg{v9cP;?R<5Hz&w)i1YTrbpNc6%p0{Khx8hi!J94klTx zC9LuDS+2u)()U%ug}~voR<>Cq}#OQfXF2)TCm)4nk4dkJK<{Ji<% zcP30SBMi`eN&Lves%5zi8b`z0j<83Tc~cBqc7F%;N9zZcNAe!JR3!n;@j1h z1lCS;R&Xw6EFbwYNCw_`r4_DiPb}ogRDYy^watxfz7Xy(zQ=RKaRMV#RY}`WgLrrF zVY?S>T2T_0_gmfEc1P>euBpQk$h-TAw(GijhS$+YK=Tg$zQ6?>D}F1vFkHMoukc{a zEy_ED8Uf0r#&yr0HH7|2|B-{vV9-6x6%+AEp3Hd}4fvb`f5|t#1a^r!L``xWv0pYp zK_sWYo?M7Ka~?Ti?_2#VSWzD;+NOTq_0`+=>-+<27aH>r;wtxc2mAJdsVzr(62hGT z)&mW2D1I;#ot)2O9iIWid6J}Na=-qm<@K(sk9ppYVwcO*IkP(P8P9ER7!PsMfNBn& za^K3zdtRPHN^c^l9lmBs5m>rjxgOV7Io|5p!v}X)j;Ax&u7K?;q%XjX_~o%@lPr_8 z*9Uqq$6~D2?gL>l^=mP&+~8z3yT!99Io|+z9QCQwYR2S? z(t}t86UG(B`86l3E&Y`O1p($K!sj_~Szh|(peg0h(+?ymZ?)sk6C*iUD89q@SVAIS z4_&>H|FtF3pZ<_*-;w|rv%!y93`xISUXVWp-T~!8n*#@16?Q}v>{P^~9I69_ z%n*6qXY%Yy!%fWkW5OADjlkEKjP5d$8>`wRrhp=ra6@iEL)prjHQ=o3@+N$WN7maZarII1Zz-rqUrBVRY znukG8!4Q$))$$`IcgoPA;izr~)m2%Wl&%&EHeRmOXUJsiSwge{CQ5;l6K*f{(Y$dK zr+Ms$jZr918R?`Rysv0Z+#6wT~L%t0b;+Q^{rT$Y_J%=|3^Wd zt6$*epNax{<>cRLLyEm2t&MjM8j1U)pYxwc-MDWDwN~$V|G#;ney}e?-YB~f0-n-M zw?G0{JBvufZPvKoY*5O85X8y3)1IFwLkMFr+5G1knQdDje8Y{BGoelP12*9EUN%KY zxk|^L1xHs)rNCp_@p0*`=#9{%r)_7IsX3T&x{b&X;mgnjUOMtgKs#ylC}%kSdtkjl z8!FE;zg-elNMzzYzDjZ0)^Ieq?HW_G)|Sg=4mBA1EloCGZTG(+tr)OPwRZ{J7OY5O z-u^rg$|QACu3Cq*Al+><3gPrW!35XM#YAriTfXw+!m_NkpMN$HY+wKfNr4L9PYUX6 zzlS_jplR*TFaNt8ide7lbsipOGdSE!+zhi$@D8y%FCwjQ$r9L{z>FOk9`c^?Kjmj` zMuYzJ3lU=4n6Q;tr@a$L?%8~af{fraE2*s=hn>Cp;YCQ#>re~C6xoCO7}(mj#Xh*k zba*^&l5yo%qnHQd!W*<-IXZ+8vnMb>c^cM={07F5{v1ulw!aVecf>C42Ir44Vz);s zT-%=b<-{YEZ*nD{U;m4uIi#wyf4G^ggB0@5%#DRIbN7hz&!Bb!hl?A6#(~|dZ%%iN z%o^Sc0oq?wn5_;1HQ*s%km5+`HK!Bq9^dL$ZL7!o2j@&piKs-)bi>dGD9BCC4PSIk zrGJIk0P-Fv?{`4G0`eU>*i`V_XN2xXw%*xTUlVENh%_|iZDkl5p@Y866#=@Xg{cbE zjZtS75AB(^xEogv2B)1x^m!0XZdCqOZ~=~2%7kuI!6E74!u_j2iau*{do^aD^2Vk^O2eW~KSv(BzRD>xw` z&*Gb6ksujl^_Fg<9{Nxn%B8jSv6jcmU+Kw5-Q&psk7EU|G|_)%rogKwNzemwy6QX^ z@ujX`ZkT$alQ%3oWJ2VOJGz{G(ukN|LF&Ga)nKml$M>IY@1F)}2mL&m6~?A)CN|YS zLi^lZj;aN$DQnmlc~AgqcDB7)?<<0=D*JMD zM3%;`BX_AsO%3+;YjwAbOnkT+m^;*q5X>@S2hO@Aa1J zJCCx~6B|ewT}HQECVls)>JqY95!(x8tJTl^D9t}c_G8p6;&167Z{2*+*qbjZdPBKR zwYTwFdQwnL?Q_fZ1S5+O2`Bi&@(s_P_cQY7?>NOU&FL}U5YmlM6yw@TASK}~;pon& z&{?aE)kw+rf)rVR1R!KIA&R@6^&5tt+oJ8h+P)7GWpbZ0xhG1hCCSz8pFjdYT5mJUum4y`e6ST z&@%+@8U+Bx-^#X6vpu~G2`=~;;97zryltTvX_;q&`r%A)oV7(xhxX1-Obw!r%_aBq zXumue@LLi`iFY=9t~-zHYJC&!zW;W6TKK3YgAe-4E5@wu_HwjtlH4Ep5vqLS-2C5$ zSxHdkc#a7g$_vSgCJ_dxxPL&~SeaPflc=j>z18KsBxhHfhSRvim6wzyuJBI@*m2g@ zc2$Hh#1|Nide`x;s zFEY{lfS)AO1(&M2`md$eil6mNBxu2_M(#la)vUt>ub2uO+!3=jb#6Ic2xq$*jBF`n z%L9sP{NK&^17myQl!*yca`I%e*{%{^D5ld#5&5Dbmw2He%xl{Z?Bv@+UmIbjXEHB5 zH5Sh@UPidw19)2ZMmXkn`O@)IsF`Fbj+RLtb$qTJ#B-vXrZ?7??}cA6N56t|TzFj4 z=rAukcL+Zk?vE$J3_QP=HeaZiJ>sPUrar&8Ao}%X-FpDz+o?UsRbtr6!(ES)@vCo94^P>R%u%q(-9wy%Duenrn)jXuW z+2hV;WWLbrH-awRI4^BBwkb{USY=a|U+=L6IJbHc+!%aSb|KB}H$ z?;wmaMfCf`2o^LLsVRHayM++C2aVlLWRbMjawRSh!|`u4I8tjLx>H>?ZR&ba(LJXj z?DRP5gyUNUnznwc)C%qsQ!aTlw6i(@viQ+~|0fLN?FR=&Mz z!m?8%ms9Zm`@?A{S+a>p-JQ}TICnZa{gktp_;s>#3Wv_=7#GC;f$M! z&TRADKS2F7Grq42P=N2(^g3PHSv9Sr5khe~OZap~yE3UUWM-{Fh{H-BGK9MOV3L#y zw*TZQX^enrYRj7iXkEaCLTZF5z%T)MU*{_RxA-*;G{sl{7ry_e1h+X~HM>NyBnnV6 zzcFEEZvv5PId&nY^VG0nqu!l%4Ln9L8OVmkfQi1}=-j_u=t%I1_~|`SZ_zv+SV@2>e1;w+Y$vY75F((`NKQU2vax&tTw!~HE>c2M3z3d>g zk@W;ee$-qtx3IgJ&cQ;-5AmGPIIdtV0YQvcV7G)N!(PWkx#qq=;AiOzb$C@x+Z zu##CR=Q`hVF-LGTr?w9-umq+&6PrkTr)T1CJ!@XV9i+em9sS#E=UO}BNMwuBrCayH zAub{V#`%5ecrycz1$eSV8<2Ikv6CQ5E=h^K%3m6h74APzqFYP{oejD^Y7o_E2b3p| zeA*LbkS?zNs8`f>wX`CuZF=Vcnc?D9l|P;QF8KedIQiHkm!f>Y3}# zl9AL|w=FC#e&CG1Vj1SX@K&6z&wEdwI}i+9}=0 zD)hP8t2qSqGq-zz1>nRbHpsOX+Ou&rc&B>1K5Z`l|60?OVRG!%y@dyXhC`Y)1x&pBnbuTa%|7f^nM;OIHu%(W6&Ci`84e(2e5z z*ThM)rgG_sjP#cQ+Xs8;_5jS%p3?)1Cd0epUI+qH6)RAoaWyIr#O{wWN#wI+_de=e zPHAv`+(8DcYwZezvF?o<#{{xGw05-!dGx*J-i6B-YsG?>W6ke;g4Hg#P+$=@?s0UEI-*Bw6RE<{1I7> zjBlz61z%K{w(Fbs@*+5i`|zyRlh@qP_iu#(*1Wcpz$is&$q|YHc+dRFT7N)#@B@znBGn$2wXOi+ggc5BJ<+2( zlI3ksg*I$2(gaUp4h9pJY${1?hgh6#mU-3e=N{4cTb2V_4R`HbSASd)X&1AJD{hd8 z^}36_R=S?hhh>k{b|Q{V4g^$!<)__{4ZCIAOzE}*nn%8FpA_Bmaub%88)q94qdSj& zU&K}EwoAH(N;V`V{ZfKgP}7P8xX{2STb>)D)y3#SF&&=+6Jz=_o8pqGbBI1lUdL(1 zD2L567hm`YXfrYLV3fz4yv?7yE!3uaicqZ7ufRny<0U&B6qh8bcqsL`r9)-JOxkXy z+l@a1(ptpJ`{M2l$g!g@DX;KZcoPP93JT=vi}|dQ!tn5*k@U)brT5a*!NEAJ2Apj0 z3jNsKvYjiiy-sUG06+A3T)f+N_X|`ZAX$1+M8W1ZaK3Nm6Dd}Xw#CnL+A?Xi*n>}B z+g^J-yeBCQ;(6yjA1~5bLwIzXXp>6syw2d^&DXBrf$G@}~y*QOne;u_UdZD^Cl zXxza$QKpgXzp22W4GZI|8N{0M2?78Z`$wi+S>waN@uSr9`u5+ghvrjfhcjQNuoDp; zk9szfi0j_VBAd2M+55}LBoF!BASF5?QV6q5zf94lQ$2goh8#I@&N4tiMK&5WOgt0H zRiGPL-7G)N zj%2#teK$kweDwBL1+DK?B#>r?tjR02JIr zUq=)|zME?3CA9?-DRGfqM+;h7w&xgGmLjhTAOdy`b%#?iM;>=l7v)^GADOA64 zy}x#1eDIpJ^iQ-mHzp5#R2_{6(~wo;npi>z4tuCy@Z6Ovw1EGFOaCWi{Qog*{?+*F cSLciz6AsI{U0tD9;7S&f z3`9H(<`G*WCN>bN493AFOi{!!!L|afI7%o`6&6lXK&2`L1YumJiZTQ+5doQ^Fu|gz zI6Nvw1cME>!8`;4iI*N+z3;u_gZtzG5&vyF~^*1 z?S1yyXYbweAFzGO*PdLxe&gE9j&{c{J=rY}9i1#6cCzdq+ASx~UzXhiC(H6orN{Ar zj;qq$yDTU7NWP@ws1J2_*G}Ykx7%{iE$G@-7-eF^Y3#}`(v#ySiIZdTj}`y+a>=Im9Vq=f1W5yxR*!@kj+Rxz&v=+4_?qb>2v z^P8^zTt$BB=j8B|JpIS7`QY>Jz4z#w<>ZT>lB09T6nS2-t-LNa`Yg!ixr}^gvZsB` z{B;rQ@uVEqwOt7oA8%Sn=e2VBs;^`dNc~|xx$^LKH+*6BuO8<1`K9&UDuw8t_%!FY zoV0NZ!^eH~qhBH?uakr4K4~ZC5VHnAA|L9#J5r^|-)7;Y zUl$mM>pDMqeipwr+7#N+YO&F-3t!twD#tH9_S*S{wQ+C`@f*(uNuw}s=xXMh&DI;Q z;_u$0c(3`5*FEq(O?pz@6#ee_pZMDAFS)(D{hdnlGw+UhHaZ&vMC3y~_HorR=oT!) zD&Jv0*w5!@vBS?MX~$>r(d*!xjZ=9%U3__Gl0?W|%cDAF&TIVSk@)+3cqc!3boGhhYzil=`)k_5%wL2pqQz`Ju@50G)sNfVj zoXGZ|Q(f3+@xx0`O2~K<`L6lJ-SXStp$#*Nk@$Du%RKJ9@n>4_fX zCq4RXG{SB86?4nquk-Hy-E#B;AN86?zpBs|J16`d(I5ZXNB^!~KL7eV0uKN-_1L$Q zfhXMkzP+y=*8|%=cJL*vJ8JS$i*h!V@e z?gp)OZL3q^qPRQ$mTS*l z!1Lo9sgwA)pzOQd7ry0nSAP)8dF^z>J#;@|{wb*sK5UU+HV4!!`0VEJLKou6^E1;q z{-F(t{g8gMTs+F%4CL8B(dE++Be1u} zQa1d_@^?2B{4?(K#G2gBZ2YKxYj^wS1vv8wb2h-K`rtLS+C4j5oS5zZQT6pjk(( zJ4B5)x)C<~DS-Jn#3lX27u>p0yp_M+jn)mGYaUy>+T%Nnb1#0!>tbyAQ%)nklRSgJ z&7=Ic?ks-hoA@5fJ^x~JiY`PYkDmW0C(plGd!Q$Ex;t|N@d~qieC9rdJUa(Jbmg%% zxJoLcUW^RY7oUugb$iXkOVyLI8AJG+ zNchYly!4G7Y^6~5nrXo&e$8p}lUVB0m<1UOEOBY-ht5+)-??6hPx|GZjRV(b``>-$ zM|{PjUt-09)0*964ZWy4qG3A!iZuCL5J4vSq$?ol?wO2=1e&!;9t z{HK#&d2T{`aKZSSV$8nw`5IF+b?d?_&_RB2Nn@S=KEJHRZ&{wfFD-HANt+d!8=g@V${FeVy<@Q=p|RCl}k1iW;RIY+rXYw+ro1J ztScYrS3bq4R+FlcH(!!*-yB2t`NcV#59x0CP?FiqC-VdG1vMIuAg3o=Td=#P|3Z0B%|-@17rLGk-6p<6~!$6~POh1kU3(XXZO`=|>$d z!lw$=5_RyEi#Jr~RP#^%iC^4A^2m;K+VClBHe2;z6Z14*Mk&|$%X0f<_lmdugY8>E zPThfcKaZ0b)2b2Pn1`Dkmvb_pUZ*zC08jjo)ep|hccB`;;R{6kL;Ts-DL%Zk@M}Ec zYe??S-~5VIlRb~$9A!25WQb$>P5#6re$4=RZ7!m^$ICJHQwLq8^3qO zSIW*0ziJfhY2#Np#+5qaD29V6USiSHHu0r%dVQte1>d!Te30L9h<8T(gM1~;2HMmK zAIaG=K2h~u$+A`Ao#yL~^C@rnmi3*Dn>*0%_Q|VFij#Is9D-CUfq|-t52LPSO>Mf;|h8QzG9r>i*kxj)D&%wf12-@hxpQE(boL;`OLW% z&4ra*97R9KXL{m{MVR>LH~jeO-Z?hkb&`yq#K-O6lT$@0DD?-g)^Uzc7T&5n8gw__ z0DpXP`45D@vQE5>CYLA9MXJba02$ioVhjTWVS5bZ6(4zN`ENe`p5>!H^k})NKh(Lb zKhik@lUA-Xx~smjY)TJqEB4J>%kshNC(AGX&hhfC|NQ3id+))>f~iYr%eBS5L6diS z0c(T7VNUk2yzB*+mM{H`dzO#=6GzJf`m=$1G@nblG}%hD(09V$W~@UCQLSS;5BqEV zWae*vfSYo>EH@?Gc;aOFp#GTWmw)f}@_j#ZYkBJ*Le`;RxE%9>G%3oHFxKHSfF_;E zFF&fw_1jO}dg1SWTfI@g(_fZ9_1ee&mj2x4J1a|pX>wLqgaW;Whu>GnNZR9Y^4s;%W zx4i1NzvUU8TZ6Uq$a?oX>%J5^9jAU9em|0;-_C;e(1}uEYG}e zr$t+qTP`-spu!U-M~AgevS79|o^g>`wAc>y@e7Vk`?z91a^qxq>GOBXzxbc8ET8gX z-7Xxv6CigTGJZUUv*`9=vmA1gzg4h49N+Y^ODZ8#@KI9`q-_X zaPu5;fuSS!*@le$mhP;#HK&jK(B1NbUvXvmPhY0_kiYDk{5AHRoIkT@vw@Z8z;F1q z7l7fCCi(MA@@nf@5q}|i{jv8-IsM&M6%o3LI{BfEQREKp4HG$@wUJ1eYx}Q!%BAIh z`K$LWk8838tEq&7|H$p$UeKq__MwZg*U!9Rnw3=(J#1>imzU))z3%$*uKvrZuZ{Wd>ES!5dgNmrfBPTZ zSl;rks&UNFhD?$g9J)KT33%MPXFTyAfBeSP=e+&fch`Iedi2_(FPHhgB&G`tFhZFY^iGZTPO8%A6S;JedWE&6Z7VgKJMLTtbV@Au;oe}a$|fo@8QFpeTE;~ z=(!{4cwATZ_x+vv)3p?oK6COMai}`b-FNw9`G;R}pRW2^Ajgt*_)SjojgA<};ZV-D zH)q&q4iEL*eWU|BFmM=S?>NY;&)5I;`<6?(5sl{jyXGx}^8>dxQX%Vtv5PEo8w6JK zToHH6efQkYp6Q3Mqvhz+s$i(tXF7XpLn?CV%Z6Oqu_p_+nw!5{zT;K*3%heMNzF;f zzun5oTzGVll(CU?9of+U+nP1y(OpU zvv~w9Sr;nLG5?3p<|70ueyyDbUY}Yd!E0=`V+1F2S@%7DUU z!+3G5v_Yp@FhhD(9o{OXys6YM@?dLP0LotS!( zZ~o{ThY!62s*m!Sg&e-XdU0#<$S=0*Pb|w{eYqaXoLkS+K6Rp~Y^EN+{G*Qi6P;tq z8XuKI#YV0>%Nz^2?6yhv9fh2b=evx?JV#`6&=bQOMZM+dz(~P{OOO4g=JV%2_LA3t zIWdLGe~6_L*6U?ZoidN$t=;E~mp$XEY0L*5)a)#9%C_**_ejXj1}SaGL~lF&7ro-L z5_Il{V)fCw*fu?YZqYMj%cgB7z3S~eAahn{_@cQMlFic3)%3UY#Noj!JH4cEvRr#S z^9EDCiHH1&FTSjo9Q4r{^K&2ha-QnFK^=vKuFYqvdxW=7K2uz)M)&XO4}*2S)oU;32*?s`tzhPoNdy zMK~{~T*=4;PVlC()T`0MfB8pTs;kbv+GgKHr(Rq!;3+S|5(B&y+n5*@z^5dLrcGjDVs3` zF=w9B8T=Q$;LA>~9`X4+qVFJ-liI=f8qb5;adlP9$i*t%;M>z~dBL;M7jh(|v1O@a za}jzx7Y{1+b#a=fVe#WfJ$C)~F&^GD!hg8&3xD97hwY{wLOxnA2;wJqo|?br07>n| zdc9}P-SQkmio~mhtX%z&MJycY7!O^|^}~~L*w+vLY!DscBm0>6jPaAr#6u#lPtl}a zn^g8A4RF_SY<9BpclX?P?PZtsH(oFGD^X@u>A2cxb^Xba#{f#>E7Bp? ztFxkR`P@dmpq)Vyx9`@uFnA8e#&tpr-DGb_G^IYIlqLQGW*i-bW1&6e29O6Y4AR#5 zvw3QcRQo|aIrZklmvExE$M4X$oUyA07_9mhM=sXuWE_~5;nT=?xmN7c}VZTZ(}?rL~jVuDCHDd zW0I>4RkJL)P{rpZ{mdS{51lA{3Pf+T`jPlbs|k>vbZN6ZbRkPI+fmPp0DeI6t7Nc~ z$NhZ%nT)>k;6(Zz50&~yf1iG^fs4sKviK#}-Dl{r>Bu~hY2DR;F}T*pmL9|4wUTbw z@xnlPQdFhr&E%R&<~6QfTI+#VgCJrYF+`(acGqTfD_@rASLH)IiT<#`a<+xCqjpL` z>#D>_%Q%UnL=``~nBcrnhfBLfp$0UGM~}`pY-%%xL2Su?1!0>O+=jhV^Q|SHHsi~S zD~0ov1zlYjfNIlt^GFNNb-;qpg1EPAM(ME^ps)?4i@M~QXic5q&!wGA8~zyJ#}kr& z^`4JJ%2R4dCKVL9!V%6$c5)Gv^*q_xt7|K06))bGDUPP7^FtSfX;?h<0|XKb062A zIY|b0!pj0C)Y$7;i^P=d-~9Mh&zQKh^`h&1%>hsw!5hUsnpx4t z<}nU3;cAnu{B7X&Vn5^sgN95?k&<*Nw-dMSz$p_Pc^$xvIFk*X^*T}DEO_*uml7(B z&nEcAJ#m?Xu}#P#5u(vuOElFSM`G;J(?_?d0s0skGYz4+p=0BMwY@=f?C04B`6n16 z7Y+?9wH$J zAxS-==YiY@80*`{n1+s)KEk056AV77g?$%2H0xq(Q))9XS&VWbRL_G=l_J9>UJl0D zL}N3`NDj2QCw^L+J)AKpGPZ04N*&EdoH2o<_uVvg5ExqK?h8cD!pAn(v{$fP*#~QU zh>wrmGmlPAjvv4qPUcCCWLhX|Ka2&~1>W*WY1;yK(tBoXnGCEf#s(&kaR8=O7&`Rb z4)NokexjR!kF~8MOFmU5aQ$lW3aOlWOo#8pn)8ot^lQLVQZO5XoZ}x``u%x;$Cmjs zwt{}jE1RV@QuzczTVvNF(%{QMY#aX3$pievr_W(l1ZA{3C6z9Llh!WOKW`#3*AYhq z-tucRhL5MYjUq^yq;P4yz(j=;Uhu<*6tg}0;12PFp$~4~hxPm_+Zg8Ct>f7*BneZNsSb8?%&Jh@KlZTTrOg zc*d4a&)A=--&QSt^&=aCKtMfi2RM(tjY0_3lN)$zC%(pMOo(G{xaW#VQD)ml*8}*( zn%f398D{+~2NGYgRbLr0gOY-ta%{uQ8}bVGoMs=E!xb*`2zR1d+}H1qgGY~B`-@YJ z>*a;j$od&444i_t&M>U#WibY2>CmtI+6%Qc>JFq&fKMxFac!J|LFhSyp@oAfvh|$Q!ky#K zhS(4BtuuI=bE{5uez>A2b4!3M+hm`g$1$&w|CB6iS~rUj(~}eO8bJK3dJ?_67ebx{ zSHS|R%y8%`=YQMnAR>?_}JgGOix59Mum~lwBBOj7l{Dr%(^B9~CeuB#Ukb0`^qvuU*Y(62BICR)&Tg!A&&-M+!2eTcS zQp|kcb?_I5@TRuW`$zm0SeN?*o>tHfJx!tLIT3p}glz!EcCx$YvH;wLhF24aiOPLh zoyM4vMhXD7pn%KA%I|SJ3pjFVbc&HshPKa%R-zM#w$p3fhA+q*C$x=DN^`o8SMD%{ zlYy6XyKVf(AvWYbX0=U|B7A&%L$qy^lSpgCbq?mNVK#inCYah3&VIO?=1DXw=#`qC zbt3TAho;;JwjNhLV1kW_T;f+5&f5zw$zb{>8{!V`+%h~%KVy-DqlO+=H=VZ=FkY%TPJGOKbO-eUMZb@k`Qw5*kXQI4 zNn-VY-V}k{dvi=NgDj)aFv2b;9&Lhj62jH0Xgt5%4NV`a$nS9VFeZ8jwL3ZT-35mn zvUwAUQ9a=cgBJ%U^%9B`*>UXEt~NPJ9a#K=jILPgIq5_LF4);`bivL2J}%hVmz_pI z&(zfWn4ASNsVrtA?CTky6@SLgnCP>dnQ&s$k2bCduV@v=0M<$2v&?X_w&f?0 zdVL4q!ob4O|06wo;ixOrj>l#y;~Gg=-=WAx*pV-hTSqte=+)3!U&FCJJ(R7IGj_tH zSk_m_@)csRD}7KQl3@|As*N?`C_c!U@vo=O(oUUM9HYTXr$fev>%5uanu%NzjR zCb4pse%58Ff_FbT99ZTs=22SCWBp8Il>D>{j4u>gKeWxhWg0&$HJ{gkdPXCf61P@& ztiI#OvjYd~D)hvhL4pdPanYqKH?T(AS0xsJjcpoa4(T1TJw`VIoTCqRpI?P*;>dsN z5f0BOf=znyxkaZ2tJWn8N$N>lK}c;lWS?W5vOBR=JKko}KC|$3Z%PH$J5|jKJ-NqE z_ZknrZ7W~D$^f(y8P~onU3Oty2J4NY*@llDx%i|JpU9&wHDK(xtG@VU#^kYat*h>i zdSLC^jL7(-#cz$a=M=p%&kPDtW4)wR`B-^()-G4{E(m^LY+5LRq%6%7l<6vOPNhVCyvY=4yUI zIx&MxLE28(nmXlm7viLOLSs$b4|GCD7I{^>sJ)bo<7qB^r=YAS^^JFY6;xwEh zZpDM~;ZEeb0~BvkTQTEG0U3VZL5j9H_mXvxdHwoPMGk8H%GZ$DSUoG};o!Bp*+kXX z`qy7&0LlzDGC5UnIv&!hC5g%LKEG*AaEI$`J|`zF9*~_UC6v2ef%Yt=w?iGS=`x{m`*tc1v}Pz zf~slY{K=p-7He#u7L@_cNMwKhd*f^(-Vaneam*r{gTf>LelwEqaEL>^IXTI3UTi}^ zZkltHCYX)!fRgkGlZFWF0F?CZ*bebcbNh5(fov2_4=P{4lkUMPb=`l~2uhFxu>7&DseW}mFpI(L7m<98w3m<&s^gYwzKLS`@ ziH2UU5yjHI=Sa0E5;z6n)mm>R$Iaaa0HpF2H=cyKrST)6aY5j>Y2EFa4KyaOJpi`Y z0cR0NFVNX;eH&s&2RLs_Wk`!X1Ktl5EXMuVY^M5^Na4ay{PgzMr(hU*GqwVm<`|tx zHqpMHc}$IYj}CnPhO8RSa9ryZ-xY7p0CWe2u`wOua|f#J0CPySsjO015zUoj^|=$R z&P!8a>m2?Q`plg2TfXWox!mch;lqB)b!%4}(i&%-8hjt^C)?8v8krgXwGp&JSbXUmUuKNKj;seLQ@+i{*gD4%I@RALNg?5Nv zHQN3d?-dcg{ZuEQo!};N-E}JHlr|#Z=D+=Y^?ah~?(8cL)5{VsbD?G)a@Zyct*NHxP>~FNNVt39Nz-u{udkt;$vC~g<^Q~(o z@!$ErW946qkAsrqYR=YH5b{$F!kam>41*1>C($G?Qu;QuA8=!KcHIVdWNDr-8-7uK zNuNiULdrZEx{d!~v71dXW?a|C=vhDe#uyuYWb4hW)6k0ypF8ER{BAwTAx;YE-wb!) zU;16Was^(;$OUp5dXvkJY0hDAS|8fn=gyP6&xSuan8cZ0vW)z(=x@DiJPDG%HphC= z- zpYdSh-(EFF=R=BYI@>x#_%jYWdLEjhM|USaBzVpNLG3+y_(R$BD_RmMas$MWs~oG^0ClV~+&9ED$w?cD|Yz+=nu2k$xd2U}uu6PP0V zCo+iBf#`{lqWxs#{-;()(J&9)cV& z*MIxg+j{>(@hd`~jcXbH;1z zth?n%0u(-3tD58KJI#tQPuPp_{T#@NnLsv#(utmIWON>=r)G}FN{F5lNBD@6U;Bn9 z>MqnKn+0+&Jbe!0Sg#XY1|IL>WT_VXUT;oA+Kv6ir{@DlMjpC8`1rDX*N^ifn3Oa- zP>v=r{|3wSjsMrp<+?rvZ1#&IQ%o*?Q%fUy9{OfIvd7w82leqs-`IVe19y5!^8?p+ z%lE(O);9mymq@O`lr{MH-Gap%a!lvK(+9_5!wv_d}s`<0wzR2F;-6sG^f)1 zfAhBE<$Hhn)^a}|--)B-fGBwkg|A}DfUPxB;ADB-k7x(+!4Wu(Z^V|l+qB6&n>1q*9dcD_jHBlT z*vR|+hTp{?KmT(AyX9Nn__#hpI{B~9Yw%ik6(uW2wP}cuI}>`1H0k-6=fBTqX`C$v zyXpzH+GeRX%|8xjW>_S<&=S+Pnr``~H$Jia)W5&2PruNUE@20Cie;tIvIjt59r&b0 zjV=c|+__#ALk??qI+k=+1B_gv^QeSsUl&j? z;p|tZ|KgJ`FMscq_bfcG=0&dhz{tYj7c4!e`8Av9+C(?nNM0J_+A`~hL2+5Y%lGV- zcj`{^cVGXwo}+cX;<;dQvT7u2?0R+qYFq{XM198e*L=}E%d_>lL3~zo=0om&Voy%^ z%h9>f^lD0ytPpr zg~{1jZAiO~^T97J@yeh09w`1xwSh24F`NSEhCjRLSXJn`%mH@4#+$x@;up2ebwIl&_3snm%EJ(YEoj{-clclgY{Q#$UL- z{G^^VuQM1Gu)n(U2vif97a;}2J2D&cm4Ei0<mZtf?9#n|`tkjxXn6KX&EI1=R@*$+Kyw>;|^ zN6TfsKa#H^pu#R*_}$O*#n-X_6q!ggu8IzGT!q@a0d4&GoYsxW{s08 zxcb6`!zl91*VjDiv#}r4pKJ1goci!UFDRc`2%OJ$tT_0@2dCnL<$j-qr9L&M`lL5D z(Jg%h*(2AFmk(S^Onhux>cB?H;>YJE=cKZwR~3}pmJcYob}zo~KupBx=(Nh~M4*nz zFreXsw&7fy?>G)Rb7uLh_>fd0az4fHf;q3Jlg~yVw=Ucr;=5V{Uqw2b-#L3OowL9U z9j+Ix`1q<;8v}WtQ-xXig+I)9(3;nXc|pGNB1^pvR0~0A$kl-?YrweTR}h1GVi

c)ijgxDm}8EsRXFt3h@+Ufr7@DN z^55r2UpdZvo*$)c`MJ_3zXBARbH%T}ifygzYy6g*WBtspGU<*Ccb`wpyW!Ui$gZ}y zo>MwK`K>f-62KfvO2{S zXF|ni6T=gB=C>=mF~5ojWS?I%DBt!ouB^&}v*S8G>5&(6>bM<0W9)PIeSXbv;v2lq zgZx&0)nJZqzUPEz=3RZouldy~VSciFe9|fxrs_KoD#u$hYz3BTu8Twxs@yt>*lp{< zm_XbpVEfL5#v}%x;+@AY<0*cV$ZF-248A&7CXCUG-9e@z7Va=V8J*&{q4I$n{~M-~K{qUmg-Y{N~tC__Y!6wZ`uS zAN=8SKnb`wARia}P{>}4q*mFJ2rt$xz9z}40>2@prKgMpJ4y?1MK zsu;8LLY(s8tNKp-L`??i35r}^567PuI=u8S&*EdFoy9Nf;48%{S#m8d=h|q*N!*Hw zE&QzCc2jn4u4(uar*pTPKCQ7DC)&Cs49?>3$7+X~)XJA`!=HT>p7`~r%@S~FvIWT% zL)t28t$h|BY!xpHnSQNXihG*>p${(0U;hi2mrwZcOUrZh0ee^UiT1oYO{3$5Hop*u zLXEN0l1qM=vD`rN)XOLJdon_5oHz3`AzpsrE1f=|*Mk1={U^)6{EcJ3kodUYZmX=p z&l4~2a)h&L*mG4|<3d+3_?Prr)`vgu$Y1U7EWIl2?@iUEd5K>;n9zxxlFNU^0vTLl zH@o9AcfQkuuVr{d?>6N1tv`70$?|*eKGqA1!uC8^rS(s+P1LOQ9lYFac+7nk_^^=}_9|LQHrRm;gm z#jgtmwd-2xd;fSm;rGSZd-@wbDeXS|)%sP&lv@b1qs`Sf43!0V?3qvsHeeF4^Q(*h z^}o7zxuRcU@`@_U0N4FIMxo}rPTLvJc{K#}XhYWmowJJ2$Yjbl`u)zkPnNIv?#GvR zeQ>x@oZ)FOm|m&l>_ivC(ek;URCk@4f5BINBIPcJedSknv#$7sL09O4r%@qb_M zz2et2d?)PSD|vhJv?jf^coe^7;*5D_(i{GoNjc@GFgNZjMJ5=HK91L-#6s_k5ZsDS zGS%RQ&sF+5eNE*3{W~3);ByDsjH9O)4$S@$?yR>?gy?){V`EPI$n>{$7kZJt&E|jq z@9tl&>KhB0wjiX?fvux_ph<@^P`xU#l~@YcVmvoP|52 zFCDST=db-|m-UT`(xE24+%n&4gZ%FnLi&Yo)!)!<`8*?XqEn@~PlG4oI{hPQc|SBA-3UqQo@Ok7n} zIAZ21l@78Rn`X^sw|ukiJP&AnypS?sjm)BYgRrvd_2vm*-zj>cKd@`Ab&91Yp=>6{)F%4)7auKu@lUJhnvWozKNZb^uG+`E@Y3=U zeK~|@uUf1nf;jWRpXQgYuqA_|MTZQJmcB;TNR^GlS{T8}iC6rO{IH|tWqO{uY5h}C zK^05FmfvX7IMk$1hE*ehH{+tKyHIa1DdB;;rJvHi z@XysN8q8vy7k-&z&tLr~zqICPT-#vO+|kk)bI{UP%}!$rHS^6TDD1uXt~a|@W*~+c z8vo^wJW;Rw34f4ZJkG`2_D~Yj%WRNd2O^Mwn=s<$0*s{9@EYCPT5v)bA~e(n|~6M0EUxGtnrcN&$s(s zzN8S(XWAcol9+ za@NCPqQw`HsBTqo#8>DWj&U^~+CTP~&69^IHqX$ty#E|%_>m7|XO7~asM|V+|Xy_l(fh&fm#RNST>VcoN?=6S_DPi%0~BG=sQt4-78)-@|b)lahBHa~PL<9jHj zNE~dl9PG02qUPM@QPu+cEDu-Af8%z}zB%Ihfge*{9Wd$&G+)E(=&9+o!^CjO`cwNdjVRH+WU`h_MXAOitJp5x3ifW{$igPf9iBj$(b=HI#x==`-hy-E&gI#->XR(BW&pMdcoR19-nNcPkY4s2bR7uK27u z;T-wi{Jv$d3tg^Khr|3zu!D-f$3GV1rd-BjB{h8+psmB&uHFO}3e<>-KnIym}P_oSC zslstp61Dm&1NiV|^pEbaNt}ZX!rh1GA<@OoA~K`yhAgd{@foOROsg!`F}gM(u1!jB zP-&PeM7Vk8W1#d^)-p1e`o(13g|c~w?dj`;4_bZu^_E|g3d=E{cLES;rdxmDH283uG=7WUKG<2~ea{IxU4q0( zBCeM((XD0e;O571>R|^u&Ev*jpsQGwzvm-2(K$^ICifY)?_e`E(umG-isbY(H;sFS z_TV{-u;uIR9OWMt?$V=eCxZbQ9k$3lC>2^A@xz~@XvD&(_uWN31AO=Zpf(=jB!lHh zOT3|j8)NsuFr00(J`~5*Aa@-yCcZDeY#2MK^7+byjE?yuYo4B|14zoWZPTeh8BIOF zi#LZ9-0pPpQq1&2arSg`YF@vQoGhb26RLwnlb*1L_^M-Vlx>giHItHpV-y+pt6ZEK z556G7lZ4?GS?qbNp_S;OAM&IlDs9+mIL@;^vinA)D6z3H9OHAVWxzHP_n^luSJ#<< zbsIty2lS^g(Tp%sL>_Jx%DMrbLPR&IRuN*2au@Mv3b3wQaDyVnmOp4Ma3Q*l1@}l- z7!@6xqcC>X;&3#^WC@2>d~Pt-WCFI;DSS*he8-yHfN>hl!&k7gZRoJWX*}IU_<3Dv zFh%O=_d;$wPTu#$88_QzeaYlJH`gOD^~u}%0AtVi0{v!P<5awgzdH2uJ`V|wUL*2lawezA2~fq&{P;mfB?8T6HUC*4h6A&Uoa8O-j$RT~z$aZBVg6 zzF?cyl6N zdHw?sJ7Tp$XXHMr#>SS7hWS(q4Vv|F6FxR`qoAKa__u1W&%AQI4T^VKan^IyU>zfs zE|$R$NQPNwnbWKcmi{dLjG5%b9r@2i8f!K??SvY4H+*lPY@EblJRiC1P#E;CqroIW z@amJ2xy(A56v{9|GuaTpMMj+DK>H#%Xah4-!k=}#^ zneQH-ALI49-brtya+(0Rs?MoH;W4xa=7q~HKFb7Z1nBuy5&@vrkTKXDY=saRII;oP z3R%&P2^nF-NYearIVR*J3O2Ys934KH3%!qF8Ezacu`vg0S*Oab^yt!p+xLq-xy5gM z#Kw5jI=`XA!CkZ&zAqE&VEj1=NFmPhl*4MSO=PEas`~e2-T71-1sApc|fu*Q}= zsYFnC_DZcy+zSDb@&j)&>t^-n;oK7;%>Y=GI zf;q6^#lf=W>#ky4S#ll)lVVQT_DO*_|C(c%5cIB9nT$1w zdZdwu#x~{=-+@S!Al?*`YqRX_$W)w|mL<42l`iKk-%cwYqIN?eH8`i)kL=}d1?JZx ztLCs2KGwvGug#(X==ud4yo;s5T!B+uNNV9YMyc!;d~C+efEeaJa{IVw7aDzJFOkR6 zSlJt<<>?A3vyx@)YW!;#RD~3cJ<+yt$FWi*K*_8K6|i@y5t3Ja zJ+H|ads>I+vjj95MRGK=^x>=qv2joEMXBp_IFN4`AdHaye#ZCSN+T3ki zEEWhGJ-%>&Q^eAnKgqhuJba{|Jl+AxddOr{Cxi+(@50!IbHi4?hjyY5LQ=XVPTEpb zyqVjwx1@vOf~d3GC@cCi=V6PSGqd|Ua>`SZ|JP5mkUUL?=|EPi{@-nlH?JLkAw z*sMbLgtgvL+o_1?*wJfZjcXpC5>GR~M4yu?y`l7N54Pg1hB01ME2+8Z!14qfU-Yz@ zpP&@C_lf&Q^@(4j;1EbkPV$`KhCay2t@XoalE&DO(HG;)bGsV$(1$|8a365@r{WKw zNW$FkEp^Sm<|7b9uV3Ad{N#D~L@0goVuYqx6L^T_<{Zg#=0otZT7J0Sg93< zJ_mX2IquB#Bm6s#^rsweb>du#$y5q2icb}=oNpi;{UA7T{^iK)*yGw5d6=pq_?*D>mRC&iQRDaItw;A9 zUwyN}YMcO55)^&3H9%p>YklyFuHBgRqrZ5o{^}Fg-RyE2Q&BkPr4P7!;2dsBBY5kZ z6MOo=-HSke#!JD&S`O^!e_!8v^T8YV)+p1?{L!gB{K1puy1vT%sWe=-JBLXqC(&~o zh8QdS8g_rYT88wPo<6+$(H>5CKO8#&q^#c>*j4hprAvR9e{%Kyt8YGf`?u>?8Tz14 zS1k!Et{sV(!ehcu#U^0M9yMmukRS`=W<1D5*Xuj%0?f#3B#i1AuV%Dk0a#p(np`Z z@Ny<>{{ZDV5+@v)mOs>&&;9Vv>-)pHaOkS3YygE%;ePHnZ!h`bKx(H9HZuLnZ`piM z2ii=ClLN3rsu>=c{+jNjKd(=0rLpid^!u4*y(mWJPG6kjm0Yv8i=0jt@0q$c?3SO6 zo`T_+i0(Myt98b;JQvD(PJ8@c_^spR4R6xbATVp;gA^fWJoolt6Viy=aHkR(bL6>a z0*u#QIOR-CHs#1eI_@gp{LgMJH~1i?ZcMM{ufkCb2He+@V%l*Br$@ccN`(OGk)9u)8Cl^IS$70>cnNtJOD;^adIv1mfzOH@{j*A zpUGT+)Iu&-&YD8$81J|E-`Afpo?Sod(=~-f1KG?W4N<>A4H|trX(W)6k{Oa&+m(#9NV~FpO<-jgq5FpLo=R80h%`t-tc094&kfl2?<-(g>J|r?=r^r}OA> zmp&f(`pX~wSI3@L@|*kMoPV!t)up3lQ3afNHGkNJ?ukAA%&S+P!*d|=aQo0Nz5YfK zKR4s_UId|>uzYyqbjJt5=GTt(Ez-yS$U9G{Cqm(9+ajN> zgT~ide(a0*RMefm>R_qQXttNTKUJiWa#G(o>gibbxL(-&eO>l^>-4Yw{;}#f=Ndog zTpjgwLr5GKkp=Bm^VjU9%39U~*@|iCk3RCfSN<|`f4G7d?}tSDTy`AIwQL?;#$97+ ztSvnwvYK=4p}Io0?fv>@g@5oyeJpBc$rtZF^xS26hCWZ4#Yok->p2VeHu^YSPUGG2k^A|XtmgmW>+a9E=9)4OCk5TSW^(Rd;pI_JfySLre zQLOv*sbCN46V?6wuS}=FN|eBT_p(bFq*`MXpIA`Vg(EMp(umI{;a4t?=!xmyYV?&H2P7PMKv=d+vjRBWh(As6Lj0Qcn$#3?!%y6`&&<3aj!!;n$@xk0 z*`QFf2~yb7*ZgYBR84)J;s=KZ&x_vE!tWtII60`G5(@|IFyHPr=5zVG<@(X_<1hTc z_kGCwAo)o&!Uw+XL*A!{f;S*LxN;y5=0e-ZrK)pdNED2liw(!iVbw-%n7!XMpG8kA zGUJMmr0RBj5-MyJddQOpL{O*s7%s{`6u+WXrgQwlI?smCIg$&Q{AYgqCt0wKb7$_% zm%{TugWsEv_{Fa|uJO;}cZ_9uLpG0)>jq*Vhu`WPlbLjiH(IU~Fm-o{X+n|rIebs+ zBK*FBMohVN%r4@=_@qH>4)KXqe5CL#cK)Tu;+Dei@z-rsKEYOe;uO{W-~*^lGv{e} zg4af91r84J?WZul<4pXy&Q9bMAD7uEiayKu@j6WtFdw~+#;%<5b$dDfR;X#?4us;} z-~EhV6zs>~=Rof`?o~=VM~9%M_?8J+n!&AcCV)?AP=;fE71{~UeEA>#S{QucDki=r zzHybu$j{hvT>Nr&n2+r=zY;+&dlw*cHh$KbFJ$UN=-6jIG7AR2vDH_c$iN1FmhpRt z?{%2s!?BZglURd~-k|DP8~&9Flv)o?mLI$Jz3h>-Z8i{UeJRS<(K9vL#!-~$F*1Sp z9>4-|wb7EC2gB>kF9$2`EI#_O(HBeOdGZy+=Ze2BPH_+Mi?qgP47=j(>kB=mJ%oMS z9r<0iE@an9F`Z)KGra&4x%#2EIrCiSSMf=2pI?~4w>$UPbpC{gT;8zlrl=Bb2 zc!MuoiVfHWSDf^|NDlF(^ZW;&*`LSHX6X1EeyW$cIeN{P*pA<}=H;OUB#~>P2l%!Y z!u69#KlsSz*U2UJ{M*;+{q-Mwz4pdlJGFtZ-+TGiS1Ql<#B&y|xO2F8BP#-G95X!= zS3AtF&0v5*jT?Lk8~!j1%0_T}otooBko6is#Sgz&6@Aj7$ONp`$^7Ks*zOGN$=Vl+ z!3WfQyRB%BY(65Ff(S*v1=yWtyJ{I0gB$4W-~OP!g>&~BlI$ss{JeWJ0Y~lvE4La}LgwmJ{B^=-^LrxrR*K+!NY34Y z%M z<9FfUS32e(gAJbEtbl5ub8iasSIo+HYW6cI2(;PPCVrX9hj6>)HIID%gYPzH@6^%v zv^{*@-@5)2n!;y#NN$bBu|)+fn^0}89(_q=8AGE|lG!A3qm}-*G$sPd@g2 zSN`*ry_F8$fdaX8yu3>5_^=Mm3a>SxDq|(W496V3gthog+!l-+gI^0x3>K~U0B9_I z@g1v9#%%cbQY(J<)|7{e%NhR$c6@0R)3;{wt|Y5hT-qAn?23((Ie*Is_;P_4Gx3j1 z3^!RMCcZ=O#~*wM_}}BBm6H6+W|(D1K9`SA_)O&v{7zZehxLm7tBQH}eC`H%|3AL+ zwv$WC=ZSiwBbOHn*aasRMW->jDp-wcQfvqt$sDPv&GGOq`KuGkd^o;c>O`@?JJE_` zdU788%6;TNa;;()znFK!uf=i(n|UXb!}$}T5F5S&N6!Fu`(`Au^2Zij=Z|V?HNBZ# z{Jg_J&>P3Qlh3>HhAVHIXs5)?*?J{TB9TPPY-Gp32p`^F3!lv=`TY2MT!#Dn_EX5YDwXjm4@%zo zyA%j0dpPZ8aUi>rp!dHqyG~d+l6Q>+x9T-*oC&4dQmFv;TYcH~Spj>DJ0esIt zzWNO+#A`{>E5i(Xk;Z0`sjgNLsQM^ePYfMu`tZTDpWqGSgiZetwnduxeT7P8ynTsi zel~9SC}kpn5&t6m<~Z?*-@e9Xw_7%@1cxGiwOUv!*ZAgV{^YpI;WyoHSsAi`#H6j9 zt$aSe;%xY&tQ7Q@%CCLw|GfH*c7B0V=63;TLHuy07aBFXpK@e@kz6>#YSGcv3{ghz zzVXF3=^Q@()T&z5KP7&Q>i!XZTNu&$kfkNQnO!8-_aDL+?R~C8sjF4t! z6x@c9tB)3F@nK85F<=By?G&Gi4}X@LiXJ2XmM&tvDMDVeZJcH{s6W+y1bgFn`9~ZXTFjEjziZ(}(o3vn z`%X>ZGshK%2W48h%Jnqix>9=bSGbGC-{Va~Hp{r_k-l2)R5e=9GXJFTue#GuTPtHLO_kpoE;{;<|N8ou=yCIP zN<{A~WY5T@7mLhsKlK)EER*b9LF?v{dT-&+=Hpvd_~PVB{13->Hs|DD_AU++MKR^? zVbs#s_)ceV^X6!`7vaB08NBAP@4xarcZzYI{jMLv_MN@||G4r!x9+?3(b^}k&qm0m zIJo%3!Mf<)XVROminu6NX7e>E)#+h2O$}L)eu$)~=3}XaGUgyZ_V8KMnK#)7zjPHp z_Ts=j%wK(OAJ%4maf|Pa51wLAKZDR6(r+-k<@J}An;-pDHxE9y+0Rj)g#6$aUwirP zX!kYxQ0mVy-QN2yL-92;)+QS*i|kvrv|fAPK+-?Jmin%y1ZS6N0LGw(w2!|y(vgZ*y#F}>^b>-1db)Nj=f;xC|Ft8@YI zMIq1nn~#0+?)d1{!hey9e+8a5izk@{Oplez2GHqrSUlSN&@^wrvVyP!giSlmuO%9r zW`jOGD83?gYTjdlCEZT%G_f_YKb`yp!)N?Qcc8y6-5c~LFW-9YpKRX@b^v?Vs?#fW z*DlT`JnOH$|Jl3C_q|fP=kqnu&(d`7^YSrkS5(VraZMu&zIv_2t3qXyto_-1d=_pk z^vbJk!~$p|XLVszAW2V_Pv+Y=r{jaEb~--#@C&o@YkYyT{(x!uak=@SdyXFer}KN5 zFTlMk$hvZOMZ0@2f4q3@#*LTjFKs?eK|fUioJEMtmjUO-<02&yOE|p|V-%X=6Xv@X(oCxjr1jf2;npdQ$tQM<2QW z=azp~pZ|S`@O0`r&8O4l#eLPLy7n@?{`u15<>(>(HP?sj)ax^gp0C0^Q@=iWK*f2c zD)fL#sXs~F-K&MVM;neWi6M8@tERwteOT%%cv{JMqtu2a&-F?ld~arKwAH@y=LKKw z#h-2EA?L&VSjQ(K-_mq$Dl8u&b4}hKRXUGo8jtD{dqj15STlZy(C<7sI)2CQ_~fnE k9@EG3{4s5ok?kb>|H;3ubeVRY^#A|>07*qoM6N<$f~C=$asU7T literal 0 HcmV?d00001 diff --git a/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/profile/backup_config.json b/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000..78f40ae7c4 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/profile/main_pages.json b/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000..1898d94f58 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/main/resources/en_US/element/string.json b/shell/platform/ohos/flutter_embedding/application/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000..a4969eae86 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/main/resources/en_US/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "ApplicationAbility_desc", + "value": "description" + }, + { + "name": "ApplicationAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/main/resources/zh_CN/element/string.json b/shell/platform/ohos/flutter_embedding/application/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000..9e08d1adfe --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "ApplicationAbility_desc", + "value": "description" + }, + { + "name": "ApplicationAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/mock/mock-config.json5 b/shell/platform/ohos/flutter_embedding/application/src/mock/mock-config.json5 new file mode 100644 index 0000000000..99db04adcd --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * 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. + */ +{ +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/FlutterInjector.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/FlutterInjector.test.ets new file mode 100644 index 0000000000..ab342916e2 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/FlutterInjector.test.ets @@ -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. + */ + +import { describe, it, expect } from '@ohos/hypium' +import { FlutterInjector } from "@ohos/flutter_ohos"; + +export default function FlutterInjectorTest() { + describe('FlutterInjectorTest', () => { + it('getInstance', 0, () => { + expect(FlutterInjector.getInstance()).not().assertNull(); + }) + it('getFlutterLoader', 0, () => { + expect(FlutterInjector.getInstance().getFlutterLoader()).not().assertNull(); + }) + it('getFlutterNapi', 0, () => { + expect(FlutterInjector.getInstance().getFlutterNapi()).not().assertNull(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/List.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000..80151e3685 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,153 @@ +/* + * 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 FlutterAbilityAndEntryDelegateTest from './embedding/ohos/FlutterAbilityAndEntryDelegateTest.test'; +import FlutterAbilityTest from './embedding/ohos/FlutterAbilityTest.test'; +import FlutterEntryTest from './embedding/ohos/FlutterEntryTest.test'; +import FlutterManagerTest from './embedding/ohos/FlutterManagerTest.test'; +import SettingTest from './embedding/ohos/SettingTest.test'; +import BinaryCodecTest from './plugin/common/BinaryCodecTest.test'; +import PlatformViewRegistryImplTest from './plugin/platform/PlatformViewRegistryImplTest.test'; +import PlatformViewWrapperTest from './plugin/platform/PlatformViewWrapperTest.test'; +import PlatformViewsControllerTest from './plugin/platform/PlatformViewsControllerTest.test'; +import RawPointerCoordTest from './plugin/platform/RawPointerCoordTest.test'; +import RootDvModelManagerTest from './plugin/platform/RootDvModelManagerTest.test'; +import ByteBufferTest from './plugin/util/ByteBufferTest.test'; +import PlatformChannelUnitTest from './embedding/engine/systemchannels/PlatformChannel.test'; +import RestorationChannelUnitTest from './embedding/engine/systemchannels/RestorationChannel.test'; +import SettingsChannelUnitTest from './embedding/engine/systemchannels/SettingsChannel.test'; +import TextInputChannelUnitTest from './embedding/engine/systemchannels/TextInputChannel.test'; +import JSONMethodCodecUnitTest from './plugin/common/JSONMethodCodec.test'; +import MethodCallUnitTest from './plugin/common/MethodCall.test'; +import AccessibilityEventsDelegateUnitTest from './plugin/platform/AccessibilityEventsDelegate.test'; + +import DartMessengerTest from './embedding/engine/dart/DartMessengerTest.test' +import ApplicationInfoTest from './embedding/engine/loader/ApplicationInfoTest.test' +import FlutterApplicationInfoTest from './embedding/engine/loader/FlutterApplicationInfoTest.test' +import FlutterLoaderTest from './embedding/engine/loader/FlutterLoaderTest.test' +import FlutterMutatorViewTest from './embedding/engine/mutatorsstack/FlutterMutatorViewTest.test' +import FlutterMutatorsStackTest from './embedding/engine/mutatorsstack/FlutterMutatorsStackTest.test' +import FlutterRendererTest from './embedding/engine/renderer/FlutterRendererTest.test' +import TouchEventProcessorTest from './embedding/ohos/TouchEventProcessorTest.test'; +import TouchEventTrackerTest from './embedding/ohos/TouchEventTrackerTest.test'; +import WindowInfoRepositoryCallbackAdapterWrapperTest from './embedding/ohos/WindowInfoRepositoryCallbackAdapterWrapperTest.test'; +import FlutterEngineTest from './embedding/engine/FlutterEngineTest.test'; +import FlutterEngineCacheTest from './embedding/engine/FlutterEngineCacheTest.test'; +import FlutterEngineConnectionRegistryTest from './embedding/engine/FlutterEngineConnectionRegistryTest.test'; +import FlutterEngineGroupCacheTest from './embedding/engine/FlutterEngineGroupCacheTest.test'; +import FlutterEngineGroupTest from './embedding/engine/FlutterEngineGroupTest.test'; +import FlutterNapiTest from './embedding/engine/FlutterNapiTest.test'; +import FlutterOverlaySurfaceTest from './embedding/engine/FlutterOverlaySurfaceTest.test'; +import FlutterShellArgsTest from './embedding/engine/FlutterShellArgsTest.test'; +import BinaryMessengerTest from './plugin/common/BinaryMessengerTest.test'; +import DartExecutorTest from './embedding/engine/dart/DartExecutorTest.test'; + +import PathUtilsTest from './plugin/util/PathUtils.test'; +import StringUtilsTest from './plugin/util/StringUtils.test'; +import ToolUtilsTest from './plugin/util/ToolUtils.test'; +import MessageChannelUtilsTest from './plugin/util/MessageChannelUtils.test'; +import LogTest from './plugin/util/Log.test'; +import TraceSectionTest from './plugin/util/TraceSection.test'; +import FlutterInjectorTest from './FlutterInjector.test'; +import SendableBinaryCodecTest from './plugin/common/SendableBinaryCodec.test'; +import dynamicViewJsonTest from './view/DynamicView/dynamicViewJson.test'; +import PlatformOverlayViewTest from './plugin/platform/PlatformOverlayView.test'; +import PlatformViewTest from './plugin/platform/PlatformView.test'; +import FlutterRunArgumentsTest from './view/FlutterRunArguments.test'; +import LifecycleChannelTest from './embedding/engine/systemchannels/LifecycleChannel.test'; +import FlutterExceptionTest from './plugin/common/FlutterException.test'; +import JSONMessageCodecTest from './plugin/common/JSONMessageCodec.test'; +import SendableJSONMessageCodecTest from './plugin/common/SendableJSONMessageCodec.test'; +import SendableJSONMethodCodecTest from './plugin/common/SendableJSONMethodCodec.test'; +import SendableStringCodecTest from './plugin/common/SendableStringCodec.test'; +import StandardMessageCodecTest from './plugin/common/StandardMessageCodec.test'; +import StandardMethodCodecTest from './plugin/common/StandardMethodCodec.test'; +import StringCodecTest from './plugin/common/StringCodec.test'; +import ListenableEditingStateTest from './plugin/editing/ListenableEditingState.test'; +import TextEditingDeltaTest from './plugin/editing/TextEditingDelta.test'; +import TextInputPluginTest from './plugin/editing/TextInputPlugin.test'; +import LocalizationPluginTest from './plugin/localization/LocalizationPlugin.test'; +import SendableStandardMessageCodecTest from './plugin/common/SendableStandardMessageCodec.test'; +import SendableStandardMethodCodecTest from './plugin/common/SendableStandardMethodCodec.test'; + +export default function testsuite() { + FlutterAbilityAndEntryDelegateTest(); + FlutterAbilityTest(); + FlutterEntryTest(); + FlutterManagerTest(); + SettingTest(); + BinaryCodecTest(); + PlatformViewRegistryImplTest(); + PlatformViewWrapperTest(); + PlatformViewsControllerTest(); + RawPointerCoordTest(); + RootDvModelManagerTest(); + ByteBufferTest(); + PlatformChannelUnitTest(); + RestorationChannelUnitTest(); + SettingsChannelUnitTest(); + TextInputChannelUnitTest(); + JSONMethodCodecUnitTest(); + MethodCallUnitTest(); + AccessibilityEventsDelegateUnitTest(); + DartMessengerTest(); + ApplicationInfoTest(); + FlutterApplicationInfoTest(); + FlutterLoaderTest() + FlutterMutatorViewTest(); + FlutterMutatorsStackTest(); + FlutterRendererTest(); + TouchEventProcessorTest(); + TouchEventTrackerTest(); + WindowInfoRepositoryCallbackAdapterWrapperTest(); + FlutterEngineTest(); + FlutterEngineCacheTest(); + FlutterEngineConnectionRegistryTest(); + FlutterEngineGroupCacheTest(); + FlutterEngineGroupTest(); + FlutterNapiTest(); + FlutterOverlaySurfaceTest(); + FlutterShellArgsTest(); + BinaryMessengerTest(); + DartExecutorTest(); + PathUtilsTest(); + StringUtilsTest(); + ToolUtilsTest(); + MessageChannelUtilsTest(); + LogTest(); + TraceSectionTest(); + FlutterInjectorTest(); + SendableBinaryCodecTest(); + dynamicViewJsonTest(); + PlatformOverlayViewTest(); + PlatformViewTest(); + PlatformViewTest(); + FlutterRunArgumentsTest(); + LifecycleChannelTest(); + FlutterExceptionTest(); + JSONMessageCodecTest(); + SendableJSONMessageCodecTest(); + SendableJSONMethodCodecTest(); + SendableStandardMessageCodecTest(); + SendableStandardMethodCodecTest(); + SendableStringCodecTest(); + StandardMessageCodecTest(); + StandardMethodCodecTest(); + StringCodecTest(); + ListenableEditingStateTest(); + TextEditingDeltaTest(); + TextInputPluginTest(); + LocalizationPluginTest(); +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineCacheTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineCacheTest.test.ets new file mode 100644 index 0000000000..73e9ca9573 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineCacheTest.test.ets @@ -0,0 +1,47 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import FlutterEngine from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine'; +import FlutterEngineCache from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineCache'; + +export default function FlutterEngineCacheTest() { + const flutterEngineCache: FlutterEngineCache = new FlutterEngineCache(); + + describe('FlutterEngineCacheTest', () => { + + it('getInstance', 0, async (done: Function) => { + console.info("uitest: getInstance begin"); + const getInstance: FlutterEngineCache = FlutterEngineCache.getInstance(); + expect(getInstance).not().assertNull(); + done(); + }) + + it('contains', 0, async (done: Function) => { + console.info("uitest: contains begin"); + const contains: boolean = flutterEngineCache.contains('test'); + expect(contains).not().assertNull(); + done(); + }) + + it('get', 0, async (done: Function) => { + console.info("uitest: contains begin"); + const get: FlutterEngine | null = flutterEngineCache.get('test'); + if(get) { + expect(get).not().assertNull(); + } + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineConnectionRegistryTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineConnectionRegistryTest.test.ets new file mode 100644 index 0000000000..01925e7b0e --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineConnectionRegistryTest.test.ets @@ -0,0 +1,68 @@ +/* + * 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 { describe, beforeAll, it, expect } from '@ohos/hypium'; +import { FlutterPlugin, } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin'; +import FlutterEngine from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine'; +import PlatformViewsController from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsController' +import common from '@ohos.app.ability.common'; +import FlutterEngineConnectionRegistry from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineConnectionRegistry'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; + +export default function FlutterEngineConnectionRegistryTest() { + let flutterEngineConnectionRegistry: FlutterEngineConnectionRegistry; + let flutterEngine: FlutterEngine; + let context: common.UIAbilityContext; + const platformViewsController = new PlatformViewsController(); + const pluginClassName = 'test'; + + describe('FlutterEngineConnectionRegistryTest', () => { + + beforeAll(() => { + context = getContext() as common.UIAbilityContext; + flutterEngine = new FlutterEngine(context, null, null, platformViewsController); + const flutterLoader = flutterEngine.getFlutterLoader(); + flutterEngineConnectionRegistry = new FlutterEngineConnectionRegistry(context, flutterEngine, flutterLoader); + }) + + it('has', 0, async (done: Function) => { + console.info("uitest: has begin"); + if (flutterEngineConnectionRegistry) { + const hasFlag = flutterEngineConnectionRegistry.has(pluginClassName); + expect(hasFlag).not().assertNull(); + } + done(); + }) + + it('get', 0, async (done: Function) => { + console.info("uitest: get begin"); + if (flutterEngineConnectionRegistry) { + const name: FlutterPlugin = flutterEngineConnectionRegistry.get(pluginClassName); + expect(name).not().assertNull(); + } + done(); + }) + + it('onSaveState', 0, async (done: Function) => { + console.info("uitest: onSaveState begin"); + const reason = AbilityConstant.StateType.CONTINUATION; + const wantParam: Record = {}; + if (flutterEngineConnectionRegistry) { + const result: AbilityConstant.OnSaveResult = flutterEngineConnectionRegistry.onSaveState(reason, wantParam); + expect(result).not().assertNull(); + } + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineGroupCacheTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineGroupCacheTest.test.ets new file mode 100644 index 0000000000..647b3e0e82 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineGroupCacheTest.test.ets @@ -0,0 +1,48 @@ +/* + * 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 { describe, expect, it } from '@ohos/hypium'; +import FlutterEngineGroupCache from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineGroupCache'; +import { FlutterEngineGroup } from '@ohos/flutter_ohos'; + +export default function FlutterEngineGroupCacheTest() { + const flutterEngineGroupCache = new FlutterEngineGroupCache(); + const engineGroupId: string = ''; + + describe('FlutterEngineGroupCacheTest', () => { + + it('instance', 0, async (done: Function) => { + console.info("uitest: instance begin"); + const instance = FlutterEngineGroupCache.instance; + expect(instance).not().assertNull(); + done(); + }) + + it('contains', 0, async (done: Function) => { + console.info("uitest: contains begin"); + const flag = flutterEngineGroupCache.contains(engineGroupId); + expect(flag).not().assertNull(); + done(); + }) + + it('get', 0, async (done: Function) => { + console.info("uitest: get begin"); + const engGroupId: FlutterEngineGroup | null = flutterEngineGroupCache.get(engineGroupId); + if (engGroupId) { + expect(engGroupId).not().assertNull(); + } + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineGroupTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineGroupTest.test.ets new file mode 100644 index 0000000000..f0190788bd --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineGroupTest.test.ets @@ -0,0 +1,53 @@ +/* + * 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 { describe, expect, it } from '@ohos/hypium'; +import FlutterEngineGroup, { Options } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineGroup'; +import { FlutterEngine } from '@ohos/flutter_ohos'; +import PlatformViewsController from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsController' +import common from '@ohos.app.ability.common'; + +export default function FlutterEngineGroupTest() { + const flutterEngineGroup = new FlutterEngineGroup(); + const platformViewsController = new PlatformViewsController(); + const context = getContext() as common.UIAbilityContext; + const args: Array = []; + + describe('FlutterEngineGroupTest', () => { + + it('checkLoader', 0, async (done: Function) => { + console.info("uitest: checkLoader begin"); + const checkLoaderCallBack = flutterEngineGroup.checkLoader(context, args); + expect(checkLoaderCallBack).not().assertNull(); + done(); + }) + + it('createAndRunEngineByOptions', 0, async (done: Function) => { + console.info("uitest: createAndRunEngineByOptions begin"); + const options = new Options(context); + const createAndRunEngineByOptionsCallBack = flutterEngineGroup.createAndRunEngineByOptions(options); + expect(createAndRunEngineByOptionsCallBack).not().assertNull(); + done(); + }) + + it('createEngine', 0, async (done: Function) => { + console.info("uitest: createEngine begin"); + if(context) { + const fng: FlutterEngine = flutterEngineGroup.createEngine(context, platformViewsController); + expect(fng).not().assertNull(); + } + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineTest.test.ets new file mode 100644 index 0000000000..fc91be86a4 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterEngineTest.test.ets @@ -0,0 +1,263 @@ +/* + * 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 { describe, beforeAll, it, expect } from '@ohos/hypium'; +import DartExecutor, { DartEntrypoint } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartExecutor'; +import { Options } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineGroup'; +import { + AccessibilityChannel, + FlutterLoader, + FlutterNapi, + FlutterRenderer, + LifecycleChannel, + LocalizationChannel, + LocalizationPlugin, + MouseCursorChannel, + NavigationChannel, + PlatformChannel, + PluginRegistry, + RestorationChannel, + SettingsChannel, + SystemChannel, + TextInputChannel +} from '@ohos/flutter_ohos'; +import ActivityControlSurface from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityControlSurface'; +import PlatformViewsController from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsController'; +import FlutterEngine from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine'; +import common from '@ohos.app.ability.common'; + +export default function FlutterEngineTest() { + const platformViewsController = new PlatformViewsController(); + let context: common.UIAbilityContext; + let flutterEngine: FlutterEngine; + + describe('FlutterEngineTest', () => { + + beforeAll(() => { + const context = getContext() as common.UIAbilityContext; + flutterEngine = new FlutterEngine(context, null, null, platformViewsController); + }) + + it('spawn', 0, async (done: Function) => { + console.info("uitest: spawn begin"); + const options = new Options(context); + let dartEntrypoint: DartEntrypoint | null = options.getDartEntrypoint(); + let initialRoute: string = options.getInitialRoute(); + let dartEntrypointArgs: Array = options.getDartEntrypointArgs(); + let eg: FlutterEngine | null = null; + if (dartEntrypoint) { + eg = await flutterEngine.spawn(context, + dartEntrypoint, + initialRoute, + dartEntrypointArgs, + platformViewsController, + false); + if (eg) { + expect(eg).not().assertNull(); + } + } + done(); + }) + + it('getLifecycleChannel', 0, async (done: Function) => { + console.info("uitest: getLifecycleChannel begin"); + if (flutterEngine) { + const lifecycleChannel: LifecycleChannel | null = flutterEngine.getLifecycleChannel(); + if (lifecycleChannel) { + expect(lifecycleChannel).not().assertNull(); + } + } + done(); + }) + + it('getNavigationChannel', 0, async (done: Function) => { + console.info("uitest: getNavigationChannel begin"); + if (flutterEngine) { + const navigationChannel: NavigationChannel | null = flutterEngine.getNavigationChannel(); + if (navigationChannel) { + expect(navigationChannel).not().assertNull(); + } + } + done(); + }) + + it('getTextInputChannel', 0, async (done: Function) => { + console.info("uitest: getTextInputChannel begin"); + if (flutterEngine) { + const textInputChannel: TextInputChannel | null = flutterEngine.getTextInputChannel(); + if (textInputChannel) { + expect(textInputChannel).not().assertNull(); + } + } + done(); + }) + + it('getPlatformChannel', 0, async (done: Function) => { + console.info("uitest: getPlatformChannel begin"); + if (flutterEngine) { + const platformChannel: PlatformChannel | null = flutterEngine.getPlatformChannel(); + if (platformChannel) { + expect(platformChannel).not().assertNull(); + } + } + done(); + }) + + it('getSystemChannel', 0, async (done: Function) => { + console.info("uitest: getSystemChannel begin"); + if (flutterEngine) { + const systemChannel: SystemChannel | null = flutterEngine.getSystemChannel(); + if (systemChannel) { + expect(systemChannel).not().assertNull(); + } + } + done(); + }) + + it('getLocaleChannel', 0, async (done: Function) => { + console.info("uitest: getLocaleChannel begin"); + if (flutterEngine) { + const localizationChannel: LocalizationChannel | null = flutterEngine.getLocaleChannel(); + if (localizationChannel) { + expect(localizationChannel).not().assertNull(); + } + } + done(); + }) + + it('getMouseCursorChannel', 0, async (done: Function) => { + console.info("uitest: getMouseCursorChannel begin"); + if (flutterEngine) { + const mouseCursorChannel: MouseCursorChannel | null = flutterEngine.getMouseCursorChannel(); + if (mouseCursorChannel) { + expect(mouseCursorChannel).not().assertNull(); + } + } + done(); + }) + + it('getFlutterNapi', 0, async (done: Function) => { + console.info("uitest: getFlutterNapi begin"); + if (flutterEngine) { + const flutterNapi: FlutterNapi = flutterEngine.getFlutterNapi(); + expect(flutterNapi).not().assertNull(); + } + done(); + }) + + it('getFlutterRenderer', 0, async (done: Function) => { + console.info("uitest: getFlutterRenderer begin"); + if (flutterEngine) { + const flutterRenderer: FlutterRenderer = flutterEngine.getFlutterRenderer(); + expect(flutterRenderer).not().assertNull(); + } + done(); + }) + + it('getDartExecutor', 0, async (done: Function) => { + console.info("uitest: getDartExecutor begin"); + if (flutterEngine) { + const dartExecutor: DartExecutor = flutterEngine.getDartExecutor(); + expect(dartExecutor).not().assertNull(); + } + done(); + }) + + it('getPlugins', 0, async (done: Function) => { + console.info("uitest: getPlugins begin"); + if (flutterEngine) { + const pluginRegistry: PluginRegistry | null = flutterEngine.getPlugins(); + if (pluginRegistry) { + expect(pluginRegistry).not().assertNull(); + } + } + done(); + }) + + it('getAbilityControlSurface', 0, async (done: Function) => { + console.info("uitest: getAbilityControlSurface begin"); + if (flutterEngine) { + const activityControlSurface: ActivityControlSurface | null = flutterEngine.getAbilityControlSurface(); + if (activityControlSurface) { + expect(activityControlSurface).not().assertNull(); + } + } + done(); + }) + + it('getSettingsChannel', 0, async (done: Function) => { + console.info("uitest: getSettingsChannel begin"); + if (flutterEngine) { + const settingsChannel: SettingsChannel | null = flutterEngine.getSettingsChannel(); + if (settingsChannel) { + expect(settingsChannel).not().assertNull(); + } + } + done(); + }) + + it('getFlutterLoader', 0, async (done: Function) => { + console.info("uitest: getFlutterLoader begin"); + if (flutterEngine) { + const flutterLoader: FlutterLoader = flutterEngine.getFlutterLoader(); + expect(flutterLoader).not().assertNull(); + } + done(); + }) + + it('getRestorationChannel', 0, async (done: Function) => { + console.info("uitest: getRestorationChannel begin"); + if (flutterEngine) { + const restorationChannel: RestorationChannel | null = flutterEngine.getRestorationChannel(); + if (restorationChannel) { + expect(restorationChannel).not().assertNull(); + } + } + done(); + }) + + it('getAccessibilityChannel', 0, async (done: Function) => { + console.info("uitest: getAccessibilityChannel begin"); + if (flutterEngine) { + const accessibilityChannel: AccessibilityChannel | null = flutterEngine.getAccessibilityChannel(); + if (accessibilityChannel) { + expect(accessibilityChannel).not().assertNull(); + } + } + done(); + }) + + it('getLocalizationPlugin', 0, async (done: Function) => { + console.info("uitest: getLocalizationPlugin begin"); + if (flutterEngine) { + const localizationChannel: LocalizationPlugin | null = flutterEngine.getLocalizationPlugin(); + if (localizationChannel) { + expect(localizationChannel).not().assertNull(); + } + } + done(); + }) + + it('getPlatformViewsController', 0, async (done: Function) => { + console.info("uitest: getPlatformViewsController begin"); + if (flutterEngine) { + const platformViewsController: PlatformViewsController | null = flutterEngine.getPlatformViewsController(); + if (platformViewsController) { + expect(platformViewsController).not().assertNull(); + } + } + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterNapiTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterNapiTest.test.ets new file mode 100644 index 0000000000..6ee93ce6ad --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterNapiTest.test.ets @@ -0,0 +1,182 @@ +/* + * 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 FlutterNapi from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterNapi'; +import ApplicationInfoLoader from '@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/ApplicationInfoLoader'; +import { FlutterRenderer } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/renderer/FlutterRenderer'; +import { common } from '@kit.AbilityKit'; +import { describe, beforeAll, it, expect } from '@ohos/hypium'; +import { EngineLifecycleListener } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine' +import { FlutterApplicationInfo, FlutterCallbackInformation } from '@ohos/flutter_ohos'; +import { resourceManager } from '@kit.LocalizationKit'; + +//jit产物默认kenel文件 +const DEFAULT_KERNEL_BLOB = "kernel_blob.bin"; +//文件路径分隔符 +const FILE_SEPARATOR = "/"; + +export default function FlutterNapiTest() { + const flutterNapi = new FlutterNapi(); + const context = getContext() as common.UIAbilityContext; + let textureId = 0; + let initResult: InitResult; + let snapshotAssetPath: string; + let flutterApplicationInfo: FlutterApplicationInfo; + let bundlePath: string; + let event: PanGestureEvent; + let assetManager: resourceManager.ResourceManager; + + describe('FlutterNapiTest', () => { + + beforeAll(() => { + if (context) { + initResult = new InitResult( + `${context.filesDir}/`, + `${context.cacheDir}/`, + `${context.filesDir}`); + snapshotAssetPath = initResult!.dataDirPath + FILE_SEPARATOR + flutterApplicationInfo!.flutterAssetsDir; + bundlePath = snapshotAssetPath + FILE_SEPARATOR + DEFAULT_KERNEL_BLOB; + flutterApplicationInfo = ApplicationInfoLoader.load(context); + assetManager = context.resourceManager; + } + const target: EventTarget = new CustomEventTarget(new CustomArea(0, 0, { + x: 0, y: 0 + }, { + x: 0, y: 0 + })); + const renderer = new FlutterRenderer(flutterNapi); + textureId = renderer.getTextureId(); + event = { + offsetX: 50, + offsetY: 50, + velocityX: 50, + velocityY: 50, + fingerList: [], + velocity: 0, + target: target, + timestamp: 0, + source: SourceType.Unknown, + pressure: 0, + tiltX: 0, + tiltY: 0, + sourceTool: SourceTool.Unknown + } + }) + + it('checkImplemented', 0, async (done: Function) => { + console.info("uitest: checkImplemented begin"); + const methodName = 'test'; + const flag = flutterNapi.checkImplemented(methodName); + expect(flag).not().assertNull(); + done(); + }) + + it('nativeLookupCallbackInformation', 0, async (done: Function) => { + console.info("uitest: nativeLookupCallbackInformation begin"); + try { + const handle = 1; + const flutterCallbackInformation: FlutterCallbackInformation | null = + FlutterNapi.nativeLookupCallbackInformation(handle); + if (flutterCallbackInformation) { + expect(flutterCallbackInformation).not().assertNull(); + } + } catch (e) { + } + done(); + }) + + it('isAttached', 0, async (done: Function) => { + console.info("uitest: isAttached begin"); + const flag: boolean = flutterNapi.isAttached(); + expect(flag).not().assertNull(); + done(); + }) + + it('spawn', 0, async (done: Function) => { + console.info("uitest: spawn begin"); + const entrypointFunctionName = 'test1'; + const pathToEntrypointFunction = 'test2'; + const initialRoute = 'test3'; + const entrypointArgs = ['test4']; + try { + const fnapi: FlutterNapi = + flutterNapi.spawn(entrypointFunctionName, pathToEntrypointFunction, initialRoute, entrypointArgs); + expect(fnapi).not().assertNull(); + } catch (e) { + } + done(); + }) + + it('computePlatformResolvedLocale', 0, async (done: Function) => { + console.info("uitest: computePlatformResolvedLocale begin"); + const strings = []; + const arr = flutterNapi.computePlatformResolvedLocale(strings); + expect(arr).not().assertNull(); + done(); + }) + + it('registerTexture', 0, async (done: Function) => { + console.info("uitest: registerTexture begin"); + const id = flutterNapi.registerTexture(textureId); + expect(id).not().assertNull(); + done(); + }) + }) +} + +class InitResult { + appStoragePath: string; + engineCachesPath: string; + dataDirPath: string; + + constructor(appStoragePath: string, + engineCachesPath: string, + dataDirPath: string) { + this.appStoragePath = appStoragePath; + this.engineCachesPath = engineCachesPath; + this.dataDirPath = dataDirPath; + } +} + +class CurEngineLifecycleListener implements EngineLifecycleListener { + onPreEngineRestart() { + + } + + onEngineWillDestroy() { + + } +} + +class CustomEventTarget implements EventTarget { + area: Area = new CustomArea(0, 0, { x: 0, y: 0 }, { x: 0, y: 0 }); + + constructor(area: Area) { + this.area = area; + } +} + +class CustomArea implements Area { + width: Length = 0; + height: Length = 0; + position: Position = { x: 0, y: 0 }; + globalPosition: Position = { x: 0, y: 0 }; + + constructor(width: Length, height: Length, position: Position, globalPosition: Position) { + this.width = width; + this.height = height; + this.position = position; + this.globalPosition = globalPosition; + } +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterOverlaySurfaceTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterOverlaySurfaceTest.test.ets new file mode 100644 index 0000000000..b98eaccdbe --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterOverlaySurfaceTest.test.ets @@ -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. + */ +import { describe, beforeAll, expect, it } from '@ohos/hypium'; +import { FlutterOverlaySurface } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterOverlaySurface'; + +export default function FlutterOverlaySurfaceTest() { + let flutterOverlaySurface: FlutterOverlaySurface; + + describe('FlutterOverlaySurfaceTest', () => { + + beforeAll(() => { + const id = 2356; + flutterOverlaySurface = new FlutterOverlaySurface(id); + }) + + it('getId', 0, async (done: Function) => { + console.info("uitest: getId begin"); + const id = flutterOverlaySurface.getId(); + expect(id).not().assertNull(); + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterShellArgsTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterShellArgsTest.test.ets new file mode 100644 index 0000000000..b92df1429d --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/FlutterShellArgsTest.test.ets @@ -0,0 +1,62 @@ +/* + * 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 { describe, expect, it } from '@ohos/hypium'; +import { abilityDelegatorRegistry } from '@kit.TestKit'; +import { Want } from '@kit.AbilityKit'; +import FlutterShellArgs from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterShellArgs'; + +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; + +export default function FlutterShellArgsTest() { + const flutterShellArgs: FlutterShellArgs = new FlutterShellArgs(); + const want: Want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + } + + describe('FlutterShellArgsTest', () => { + + it('fromWant', 0, async (done: Function) => { + console.info("uitest: fromWant begin"); + try { + const flutterShellArgs = FlutterShellArgs.fromWant(want); + if (flutterShellArgs) { + expect(flutterShellArgs).not().assertNull(); + } + } catch (e) { + } + done(); + }) + + it('checkArg', 0, async (done: Function) => { + console.info("uitest: checkArg begin"); + const argKey = 'argKey'; + const argFlag = 'argFlag'; + try { + const flutterShellArgs = FlutterShellArgs.fromWant(want); + FlutterShellArgs.checkArg(argKey, argFlag, want, flutterShellArgs); + } catch (e) { + } + done(); + }) + + it('toArray', 0, async (done: Function) => { + console.info("uitest: toArray begin"); + const toArray = flutterShellArgs.toArray(); + expect(toArray).not().assertNull(); + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/dart/DartExecutorTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/dart/DartExecutorTest.test.ets new file mode 100644 index 0000000000..6577fa556c --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/dart/DartExecutorTest.test.ets @@ -0,0 +1,70 @@ +/* + * 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 { describe, beforeAll, expect, it } from '@ohos/hypium'; +import { common } from '@kit.AbilityKit'; +import { Options } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineGroup'; +import { DartEntrypoint } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartExecutor'; +import { resourceManager } from '@kit.LocalizationKit'; +import DartExecutor from '@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartExecutor'; +import FlutterNapi from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterNapi'; + +export default function DartExecutorTest() { + const flutterNapi = new FlutterNapi(); + let context: common.UIAbilityContext; + let dartExecutor: DartExecutor; + let options: Options; + let assetManager: resourceManager.ResourceManager; + let dartEntrypoint: DartEntrypoint | null = null; + let resourceManager: resourceManager.ResourceManager; + + describe('DartExecutorTest', () => { + + beforeAll(() => { + context = getContext() as common.UIAbilityContext; + assetManager = context.resourceManager; + resourceManager = context.resourceManager; + dartExecutor = new DartExecutor(flutterNapi, assetManager); + options = new Options(context); + dartEntrypoint = options.getDartEntrypoint(); + }) + + it('isExecutingDart', 0, async (done: Function) => { + console.info("uitest: isExecutingDart begin"); + if (dartExecutor) { + const isExecutingDart = dartExecutor.isExecutingDart(); + expect(isExecutingDart).not().assertNull(); + } + done(); + }) + + it('getBinaryMessenger', 0, async (done: Function) => { + console.info("uitest: getBinaryMessenger begin"); + if (dartExecutor) { + const binaryMessenger = dartExecutor.getBinaryMessenger(); + expect(binaryMessenger).not().assertNull(); + } + done(); + }) + + it('makeBackgroundTaskQueue', 0, async (done: Function) => { + console.info("uitest: makeBackgroundTaskQueue begin"); + if (dartExecutor) { + const taskQueue = dartExecutor.makeBackgroundTaskQueue(); + expect(taskQueue).not().assertNull(); + } + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/dart/DartMessengerTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/dart/DartMessengerTest.test.ets new file mode 100644 index 0000000000..c48bad263f --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/dart/DartMessengerTest.test.ets @@ -0,0 +1,47 @@ +/* + * 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 { DartMessenger} from '@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartMessenger' +import { describe,it, expect } from '@ohos/hypium'; +import FlutterNapi from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterNapi' +import { + TaskQueue, +} from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger' +export default function DartMessengerTest() { + describe('FlutterDartMessengerTest', () => { + it('TestMakeBackgroundTaskQueue', 0, async (done: Function) => { + const flutterNapi: FlutterNapi = new FlutterNapi(); + const dartMessage = new DartMessenger(flutterNapi); + let taskQueue: TaskQueue = dartMessage.makeBackgroundTaskQueue(); + expect(taskQueue).not().assertNull(); + done(); + }) + + it('TestGetPendingChannelResponseCount', 0, async (done: Function) => { + const flutterNapi: FlutterNapi = new FlutterNapi(); + const messenger = new DartMessenger(flutterNapi); + let count: number = messenger.getPendingChannelResponseCount(); + expect(count).assertEqual(0); + done(); + }) + + it('TestAskQueueFactory', 0, async (done: Function) => { + const flutterNapi: FlutterNapi = new FlutterNapi(); + const messenger = new DartMessenger(flutterNapi); + expect(messenger.taskQueueFactory).not().assertNull(); + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/loader/ApplicationInfoTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/loader/ApplicationInfoTest.test.ets new file mode 100644 index 0000000000..00fe21a0e9 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/loader/ApplicationInfoTest.test.ets @@ -0,0 +1,28 @@ +/* + * 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 common from '@ohos.app.ability.common'; +import ApplicationInfoLoader from '@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/ApplicationInfoLoader' +import { describe,it, expect } from '@ohos/hypium'; +export default function ApplicationInfoTest() { + describe('ApplicationInfoTest', () => { + it('TestLoad', 0, async (done: Function) => { + let context: common.Context = getContext(); + let applicationInfo = ApplicationInfoLoader.load(context) + expect(applicationInfo).not().assertNull(); + done(); + }) + }) +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/loader/FlutterApplicationInfoTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/loader/FlutterApplicationInfoTest.test.ets new file mode 100644 index 0000000000..7556ae740f --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/loader/FlutterApplicationInfoTest.test.ets @@ -0,0 +1,26 @@ +/* + * 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 FlutterApplicationInfo from '@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/FlutterApplicationInfo' +import { describe, it, expect } from '@ohos/hypium'; +export default function FlutterApplicationInfoTest() { + describe('FlutterApplicationInfoTest', () => { + it('TestLoad', 0, async (done: Function) => { + let flutterApplicationInfo = new FlutterApplicationInfo("test", "test", "test", "test", "test", "test", false) + expect(flutterApplicationInfo).not().assertNull(); + done(); + }) + }) +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/loader/FlutterLoaderTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/loader/FlutterLoaderTest.test.ets new file mode 100644 index 0000000000..52e231dcd9 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/loader/FlutterLoaderTest.test.ets @@ -0,0 +1,52 @@ +/* + * 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 common from '@ohos.app.ability.common'; +import FlutterLoader from '@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/FlutterLoader' +import { describe,it, expect } from '@ohos/hypium'; +import FlutterNapi from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterNapi' +export default function FlutterLoaderTest() { + describe('FlutterLoaderTest', () => { + it('initializationTest', 0, async (done: Function) => { + let flutterNapi: FlutterNapi = new FlutterNapi(); + let flutterLoader: FlutterLoader = new FlutterLoader(flutterNapi); + expect(flutterLoader.initialized).assertFalse(); + done(); + }) + + it('initResultTest', 0, async (done: Function) => { + let flutterNapi: FlutterNapi = new FlutterNapi(); + let flutterLoader: FlutterLoader = new FlutterLoader(flutterNapi); + expect(flutterLoader.initResult).assertNull(); + done(); + }) + + it('flutterNapiTest', 0, async (done: Function) => { + let flutterNapi: FlutterNapi = new FlutterNapi(); + let flutterLoader: FlutterLoader = new FlutterLoader(flutterNapi); + expect(flutterLoader.flutterNapi).not().assertNull(); + done(); + }) + + it('startInitializationTest', 0, async (done: Function) => { + let flutterNapi: FlutterNapi = new FlutterNapi(); + let flutterLoader: FlutterLoader = new FlutterLoader(flutterNapi); + let context: common.Context = getContext(); + expect(flutterLoader.initialized).assertFalse(); + flutterLoader.startInitialization(context); + done(); + }) + }) +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/mutatorsstack/FlutterMutatorViewTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/mutatorsstack/FlutterMutatorViewTest.test.ets new file mode 100644 index 0000000000..4924e8b78a --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/mutatorsstack/FlutterMutatorViewTest.test.ets @@ -0,0 +1,27 @@ +/* + * 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 { FlutterMutatorView } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorView' +import { describe,it, expect } from '@ohos/hypium'; +export default function FlutterMutatorViewTest() { + describe('FlutterMutatorViewTest', () => { + it('TestGetDvModel', 0, async (done: Function) => { + let flutterMutatorView = new FlutterMutatorView(); + let dvModel = flutterMutatorView.getDvModel(); + expect(dvModel).not().assertNull(); + done(); + }) + }) +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/mutatorsstack/FlutterMutatorsStackTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/mutatorsstack/FlutterMutatorsStackTest.test.ets new file mode 100644 index 0000000000..4c633425ba --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/mutatorsstack/FlutterMutatorsStackTest.test.ets @@ -0,0 +1,90 @@ +/* + * 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 common from '@ohos.app.ability.common'; +import { + FlutterMutatorsStack, + FlutterMutator +} from '@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorsStack' +import { describe,it, expect } from '@ohos/hypium'; +import matrix4 from '@ohos.matrix4' +export default function FlutterMutatorsStackTest() { + describe('FlutterMutatorsStackTest', () => { + it('TestPushClipPath', 0, async (done: Function) => { + let flutterMutatorStack = new FlutterMutatorsStack(); + const width = 100; + const height = 200; + const command = 'M 10 10 L 90 90'; + flutterMutatorStack.pushClipPath(width, height, command); + expect(flutterMutatorStack.getMutators().length).assertEqual(1); + expect(flutterMutatorStack.getFinalClippingPaths().length).assertEqual(1); + done(); + }) + + it('TestPushClipRect1', 0, async (done: Function) => { + let flutterMutatorStack = new FlutterMutatorsStack(); + const width = 100; + const height = 200; + const radius = 10; + flutterMutatorStack.pushClipRect(width, height, radius); + expect(flutterMutatorStack.getMutators().length).assertEqual(1); + done(); + }) + + it('TestPushClipRect2', 0, async (done: Function) => { + let flutterMutatorStack = new FlutterMutatorsStack(); + const width = 100; + const height = 200; + const radius = 10; + flutterMutatorStack.pushClipRect(width, height, radius); + expect(flutterMutatorStack.getFinalClippingRects().length).assertEqual(1); + done(); + }) + + it('TestPushTransform1', 0, async (done: Function) => { + const values = [1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; + let flutterMutatorStack = new FlutterMutatorsStack(); + flutterMutatorStack.pushTransform(values); + expect(flutterMutatorStack.getMutators().length).assertEqual(1); + done(); + }) + + it('TestPushTransform2', 0, async (done: Function) => { + const values = [1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; + let flutterMutatorStack = new FlutterMutatorsStack(); + flutterMutatorStack.pushTransform(values); + expect(flutterMutatorStack.getMutators().length).assertEqual(1); + done(); + }) + + it('TestFlutterMutatorsStack1', 0, async (done: Function) => { + let flutterMutatorStack = new FlutterMutatorsStack(); + expect(flutterMutatorStack.getMutators().length).assertEqual(0); + done(); + }) + + it('TestFlutterMutatorsStack2', 0, async (done: Function) => { + let flutterMutatorStack = new FlutterMutatorsStack(); + expect(flutterMutatorStack.getFinalClippingPaths().length).assertEqual(0); + done(); + }) + + it('TestFlutterMutatorsStack3', 0, async (done: Function) => { + let flutterMutatorStack = new FlutterMutatorsStack(); + expect(flutterMutatorStack.getFinalClippingRects().length).assertEqual(0); + done(); + }) + }) +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/renderer/FlutterRendererTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/renderer/FlutterRendererTest.test.ets new file mode 100644 index 0000000000..169f510280 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/renderer/FlutterRendererTest.test.ets @@ -0,0 +1,58 @@ +/* + * 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 { describe,it, expect } from '@ohos/hypium'; +import { FlutterRenderer} from '@ohos/flutter_ohos/src/main/ets/embedding/engine/renderer/FlutterRenderer'; +import FlutterNapi from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterNapi' +export default function FlutterRendererTest() { + describe('FlutterRendererTest', () => { + it('TestCreateSurfaceTexture', 0, async (done: Function) => { + let flutterNapi: FlutterNapi = new FlutterNapi(); + let flutterRenderer = new FlutterRenderer(flutterNapi); + let surfaceTextureEntry = flutterRenderer.createSurfaceTexture(); + expect(surfaceTextureEntry).not().assertNull();; + done(); + }) + + it('TestGetTextureId', 0, async (done: Function) => { + let flutterNapi: FlutterNapi = new FlutterNapi(); + let flutterRenderer = new FlutterRenderer(flutterNapi); + let textureId = flutterRenderer.getTextureId(); + expect(textureId == 0).assertFalse(); + done(); + }) + + it('TestRegisterPixelMap', 0, async (done: Function) => { + let flutterNapi: FlutterNapi = new FlutterNapi(); + let flutterRenderer = new FlutterRenderer(flutterNapi); + const pixelMap = {} as PixelMap; + let textureId = flutterRenderer.registerPixelMap(pixelMap); + expect(textureId).assertEqual(1); + done(); + }) + + it('TestRegisterPixelMapMore', 0, async (done: Function) => { + let flutterNapi: FlutterNapi = new FlutterNapi(); + let flutterRenderer = new FlutterRenderer(flutterNapi); + const pixelMap1 = {} as PixelMap; + const pixelMap2 = {} as PixelMap; + const textureId1 = flutterRenderer.registerPixelMap(pixelMap1); + const textureId2 = flutterRenderer.registerPixelMap(pixelMap2); + expect(textureId1).assertEqual(1); // 第一次调用 + expect(textureId2).assertEqual(2); // 第二次调用 + done(); + }) + }) +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/LifecycleChannel.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/LifecycleChannel.test.ets new file mode 100644 index 0000000000..61590d0821 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/LifecycleChannel.test.ets @@ -0,0 +1,71 @@ +/* + * 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 { describe, beforeEach, it, expect } from '@ohos/hypium' +import LifecycleChannel from '@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/LifecycleChannel'; +import Any from '@ohos/flutter_ohos/src/main/ets/plugin/common/Any'; + +export default function LifecycleChannelTest() { + describe('LifecycleChannelTest', () => { + let lifecycleChannel: LifecycleChannel; + let dartExecutorMock: Any; + let basicMessageChannelMock: Any; + beforeEach(() => { + dartExecutorMock = { + send: (channelName: string, message: string) => { + } + }; + basicMessageChannelMock = { + send: (message: string) => { + } + }; + lifecycleChannel = new LifecycleChannel(dartExecutorMock as Any); + (lifecycleChannel as Any).channel = basicMessageChannelMock; + }); + it('should send resumed state with focus', 0, () => { + lifecycleChannel.appIsResumed(); + lifecycleChannel.aWindowIsFocused(); + expect(basicMessageChannelMock.send).not().assertEqual('AppLifecycleState.resumed'); + }) + it('should send inactive state without focus', 0, () => { + lifecycleChannel.appIsResumed(); + lifecycleChannel.noWindowsAreFocused(); + expect(basicMessageChannelMock.send).not().assertEqual('AppLifecycleState.inactive'); + }) + it('should send inactive state when app is inactive', 0, () => { + lifecycleChannel.appIsInactive(); + lifecycleChannel.aWindowIsFocused(); + expect(basicMessageChannelMock.send).not().assertEqual('AppLifecycleState.inactive'); + }) + it('should send paused state when app is paused', 0, () => { + lifecycleChannel.appIsPaused(); + lifecycleChannel.aWindowIsFocused(); + expect(basicMessageChannelMock.send).not().assertEqual('AppLifecycleState.paused'); + }) + it('should send detached state when app is detached', 0, () => { + lifecycleChannel.appIsDetached(); + lifecycleChannel.aWindowIsFocused(); + expect(basicMessageChannelMock.send).not().assertEqual('AppLifecycleState.detached'); + }) + it('should not send duplicate state', 0, () => { + lifecycleChannel.appIsResumed(); + lifecycleChannel.aWindowIsFocused(); + (lifecycleChannel as Any).lastFlutterState = 'AppLifecycleState.resumed'; + + lifecycleChannel.appIsResumed(); + lifecycleChannel.aWindowIsFocused(); + expect(basicMessageChannelMock.send).not().assertEqual(1); + }) + }) +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/PlatformChannel.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/PlatformChannel.test.ets new file mode 100644 index 0000000000..1b6bb22329 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/PlatformChannel.test.ets @@ -0,0 +1,102 @@ +/* + * 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 { describe, expect, it, } from "@ohos/hypium"; +import { AsyncCallback as _AsyncCallback } from '@ohos.base'; +import PlatformChannel, { + Brightness, + ClipboardContentFormat, + DeviceOrientation, + HapticFeedbackType, + SystemUiMode, + SystemUiOverlay +} from "@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel"; +import { Any, DartExecutor, FlutterNapi, MethodResult } from "@ohos/flutter_ohos"; +import { resourceManager } from "@kit.LocalizationKit"; + +export default function PlatformChannelUnitTest() { + describe('PlatformChannelTest', () => { + it('platformChannel_decodeOrientations', 0, decodeOrientations); + + it('platformChannel_getFeedbackTypeFromValue', 0, getFeedbackTypeFromValue); + + it('platformChannel_getClipboardContentFormatFromValue', 0, getClipboardContentFormatFromValue); + + it('platformChannel_getSystemUiOverlayFromValue', 0, getSystemUiOverlayFromValue); + + it('platformChannel_getSystemUiModeFromValue', 0, getSystemUiModeFromValue); + + it('platformChannel_getBrightnessFromValue', 0, getBrightnessFromValue); + + it('platformChannel_getDeviceOrientationFromValue', 0, getDeviceOrientationFromValue); + }) +} + +function decodeOrientations() { + let channel = getPlatformChannel(); + expect(channel.decodeOrientations([DeviceOrientation.PORTRAIT_UP])).assertInstanceOf("Number") +} + +function getFeedbackTypeFromValue() { + let channel = getPlatformChannel(); + let result = channel.getFeedbackTypeFromValue(HapticFeedbackType.STANDARD); + expect(result).assertInstanceOf("String") +} + +function getClipboardContentFormatFromValue() { + let channel = getPlatformChannel(); + let result = channel.getClipboardContentFormatFromValue(ClipboardContentFormat.PLAIN_TEXT); + expect(result).assertInstanceOf("String") +} + +function getSystemUiOverlayFromValue() { + let channel = getPlatformChannel(); + let result = channel.getSystemUiOverlayFromValue(SystemUiOverlay.BOTTOM_OVERLAYS); + expect(result).assertInstanceOf("String") +} + +function getSystemUiModeFromValue() { + let channel = getPlatformChannel(); + let result = channel.getSystemUiModeFromValue(SystemUiMode.IMMERSIVE); + expect(result).assertInstanceOf("String") +} + +function getBrightnessFromValue() { + let channel = getPlatformChannel(); + let result = channel.getBrightnessFromValue(Brightness.LIGHT); + expect(result).assertInstanceOf("String") +} + +function getDeviceOrientationFromValue() { + let channel = getPlatformChannel(); + let result = channel.getDeviceOrientationFromValue(DeviceOrientation.PORTRAIT_UP); + expect(result).assertInstanceOf("String") +} + +function getPlatformChannel(): PlatformChannel { + let flutterNapi = new FlutterNapi(); + let manager: resourceManager.ResourceManager = getContext().resourceManager; + let dartExecutor = new DartExecutor(flutterNapi, manager); + let channel = new PlatformChannel(dartExecutor); + return channel; +} + +export class MethodResultTest implements MethodResult { + success = (result: Any): void => { + }; + error = (errorCode: string, errorMessage: string, errorDetails: Any): void => { + }; + notImplemented = (): void => { + } +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/RestorationChannel.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/RestorationChannel.test.ets new file mode 100644 index 0000000000..7a692e1ad8 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/RestorationChannel.test.ets @@ -0,0 +1,71 @@ +/* + * 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 { + DartExecutor, + FlutterNapi, + MethodCall, + MethodCallHandler, + MethodChannel, + MethodResult, + RestorationChannel, + StandardMethodCodec +} from "@ohos/flutter_ohos"; +import { describe, expect, it } from "@ohos/hypium"; +import { resourceManager } from "@kit.LocalizationKit"; +import { util } from "@kit.ArkTS"; + +let TAG = "RestorationChannel"; + +export default function RestorationChannelUnitTest() { + + describe('RestorationChannelTest', () => { + it("RestorationChannel_getRestorationData", 0, getRestorationData); + }) +} + +function getRestorationData() { + let channel = getRestorationChannel(); + expect(channel.getRestorationData()).assertInstanceOf("Uint8Array") +} + +function getRestorationChannel(): RestorationChannel { + let flutterNapi = new FlutterNapi(); + let manager: resourceManager.ResourceManager = getContext().resourceManager; + let dartExecutor = new DartExecutor(flutterNapi, manager); + let rawChannel = new MethodChannel(dartExecutor, "flutter/mousecursor", StandardMethodCodec.INSTANCE); + let restorationChannel = new RestorationChannel(rawChannel, false); + return restorationChannel; +} + +class TestMethodCallHandler implements MethodCallHandler { + onMethodCall(call: MethodCall, result: MethodResult): void { + } +} + +/** + * string转Uint8Array + * @param value + * @returns + */ +export function stringToUint8Array(str: string): Uint8Array { + try { + let textEncoder = new util.TextEncoder("utf-8"); + let array: Uint8Array = textEncoder.encodeInto(str); + return array + } catch (err) { + return new Uint8Array() + } +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/SettingsChannel.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/SettingsChannel.test.ets new file mode 100644 index 0000000000..ae6ac3ed60 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/SettingsChannel.test.ets @@ -0,0 +1,38 @@ +/* + * 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 { describe, expect, it } from "@ohos/hypium"; +import { resourceManager } from "@kit.LocalizationKit"; +import { DartExecutor, FlutterNapi, SettingsChannel } from "@ohos/flutter_ohos"; + +export default function SettingsChannelUnitTest() { + describe('SettingsChannelTest', () => { + it("SettingsChannel_startMessage", 0, startMessage); + }) +} + +function startMessage() { + let channel = getSettingsChannel(); + let result = channel.startMessage(); + expect(result).assertInstanceOf("Object"); +} + +function getSettingsChannel(): SettingsChannel { + let flutterNapi = new FlutterNapi(); + let manager: resourceManager.ResourceManager = getContext().resourceManager; + let dartExecutor = new DartExecutor(flutterNapi, manager); + let channel = new SettingsChannel(dartExecutor); + return channel; +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/TextInputChannel.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/TextInputChannel.test.ets new file mode 100644 index 0000000000..5266cefa3c --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/engine/systemchannels/TextInputChannel.test.ets @@ -0,0 +1,38 @@ +/* + * 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 { describe, expect, it } from "@ohos/hypium"; +import { resourceManager } from "@kit.LocalizationKit"; +import { DartExecutor, FlutterNapi, TextInputChannel } from "@ohos/flutter_ohos"; + +export default function TextInputChannelUnitTest() { + describe('TextInputChannel', () => { + it("TextInputChannel_createEditingStateJSON", 0, createEditingStateJSON); + }) +} + +function createEditingStateJSON() { + let textInputChannel = getTextInputChannel(); + let result = textInputChannel.createEditingStateJSON("test", 0, 1, 0, 2); + expect(result).assertInstanceOf("Object"); +} + +function getTextInputChannel(): TextInputChannel { + let flutterNapi = new FlutterNapi(); + let manager: resourceManager.ResourceManager = getContext().resourceManager; + let dartExecutor = new DartExecutor(flutterNapi, manager); + let channel = new TextInputChannel(dartExecutor); + return channel; +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterAbilityAndEntryDelegateTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterAbilityAndEntryDelegateTest.test.ets new file mode 100644 index 0000000000..3c7d611d78 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterAbilityAndEntryDelegateTest.test.ets @@ -0,0 +1,78 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry } from '@kit.TestKit'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import { FlutterAbilityAndEntryDelegate } from "@ohos/flutter_ohos"; +import { Options } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineGroup'; +import { Want } from '@kit.AbilityKit'; + +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; + +export default function FlutterAbilityAndEntryDelegateTest() { + describe('FlutterAbilityAndEntryDelegateTest', () => { + + it('TestAddEntrypointOptions', 0, async (done: Function) => { + const flutterAbilityAndEntryDelegate: FlutterAbilityAndEntryDelegate = new FlutterAbilityAndEntryDelegate(); + const options: Options = new Options(getContext()); + const result = flutterAbilityAndEntryDelegate.addEntrypointOptions(options); + expect(result).not().assertNull(); + done(); + }) + + it('TestShouldDispatchAppLifecycleState', 0, async (done: Function) => { + const flutterAbilityAndEntryDelegate: FlutterAbilityAndEntryDelegate = new FlutterAbilityAndEntryDelegate(); + const result = flutterAbilityAndEntryDelegate.shouldDispatchAppLifecycleState(); + expect(result).not().assertNull(); + done(); + }) + + it('TestGetFlutterNapi', 0, async (done: Function) => { + const flutterAbilityAndEntryDelegate: FlutterAbilityAndEntryDelegate = new FlutterAbilityAndEntryDelegate(); + const result = flutterAbilityAndEntryDelegate.getFlutterNapi(); + expect(result).assertNull(); + done(); + }) + + it('TestOnSaveState', 0, async (done: Function) => { + const flutterAbilityAndEntryDelegate: FlutterAbilityAndEntryDelegate = new FlutterAbilityAndEntryDelegate(); + const reason: AbilityConstant.StateType = AbilityConstant.StateType.CONTINUATION + const want: Want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + } + const wantParam: Record = { + "testParams": want + } + const result = flutterAbilityAndEntryDelegate.onSaveState(reason, wantParam); + expect(result).assertEqual(5); + done(); + }) + + it('TestIsFlutterEngineFromHost', 0, async (done: Function) => { + const flutterAbilityAndEntryDelegate: FlutterAbilityAndEntryDelegate = new FlutterAbilityAndEntryDelegate(); + const result = flutterAbilityAndEntryDelegate.isFlutterEngineFromHost(); + expect(result).not().assertNull(); + done(); + }) + + it('TestGetFlutterEngine', 0, async (done: Function) => { + const flutterAbilityAndEntryDelegate: FlutterAbilityAndEntryDelegate = new FlutterAbilityAndEntryDelegate(); + const result = flutterAbilityAndEntryDelegate.getFlutterEngine(); + expect(result).assertNull(); + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterAbilityTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterAbilityTest.test.ets new file mode 100644 index 0000000000..7954b9f73b --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterAbilityTest.test.ets @@ -0,0 +1,158 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry } from '@kit.TestKit'; +import { Want } from '@kit.AbilityKit'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import { FlutterView, FlutterAbility, FlutterEngine, FlutterPlugin } from "@ohos/flutter_ohos"; +import { FlutterPluginBinding } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin'; + +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +const want: Want = { + bundleName: bundleName, + abilityName: 'EntryAbility' +} + +function sleep(time: number) { + return new Promise((resolve: Function) => setTimeout(resolve, time)); +} + +export default function FlutterAbilityTest() { + describe('FlutterAbilityTest', () => { + it('FlutterAbilityTest', 0, async (done: Function) => { + const flutterAbility: FlutterAbility = new FlutterAbility(); + const flutterView: FlutterView | null = flutterAbility.getFlutterView(); + expect(flutterView).assertNull(); + await sleep(1000); + const pagePath: string = flutterAbility.pagePath(); + expect(pagePath).assertEqual("pages/Index"); + done(); + }) + + it('TestFlutterAbilityOnSaveState', 0, async (done: Function) => { + const flutterAbility: FlutterAbility = new FlutterAbility(); + const reason: AbilityConstant.StateType = AbilityConstant.StateType.CONTINUATION + const wantParam: Record = { + "testParams": want + } + await sleep(1000); + const result = flutterAbility.onSaveState(reason, wantParam); + expect(result).not().assertNull(); + done(); + }) + + it('TestGetWant', 0, async (done: Function) => { + const flutterAbility: FlutterAbility = new FlutterAbility(); + const result = flutterAbility.getWant(); + expect(result).assertUndefined(); + done(); + }) + + it('TestGetFlutterAbilityAndEntryDelegate', 0, async (done: Function) => { + const flutterAbility: FlutterAbility = new FlutterAbility(); + const result = flutterAbility.getFlutterAbilityAndEntryDelegate(); + expect(result).assertNull(); + done(); + }) + + it('TestShouldDispatchAppLifecycleState', 0, async (done: Function) => { + const flutterAbility: FlutterAbility = new FlutterAbility(); + const result = flutterAbility.shouldDispatchAppLifecycleState(); + expect(result).assertTrue(); + done(); + }) + + it('TestProvideFlutterEngine', 0, async (done: Function) => { + const flutterAbility: FlutterAbility = new FlutterAbility(); + const result = flutterAbility.provideFlutterEngine(getContext()); + expect(result).assertNull(); + done(); + }) + + it('TestProvidePlatformPlugin', 0, async (done: Function) => { + const flutterAbility: FlutterAbility = new FlutterAbility(); + const flutterEngine = new FlutterEngine(getContext(), null, null, null); + const result = flutterAbility.providePlatformPlugin(flutterEngine); + expect(result).not().assertNull(); + done(); + }) + + it('TestPopSystemNavigator', 0, async (done: Function) => { + const flutterAbility: FlutterAbility = new FlutterAbility(); + const result = flutterAbility.popSystemNavigator(); + expect(result).assertFalse(); + done(); + }) + + it('TestShouldAttachEngineToAbility', 0, async (done: Function) => { + const flutterAbility: FlutterAbility = new FlutterAbility(); + const result = flutterAbility.shouldAttachEngineToAbility(); + expect(result).assertTrue(); + done(); + }) + + it('TestGetDartEntrypointLibraryUri', 0, async (done: Function) => { + const flutterAbility: FlutterAbility = new FlutterAbility(); + const result = flutterAbility.getDartEntrypointLibraryUri(); + expect(result).assertEqual(""); + done(); + }) + + it('TestGetAppBundlePath', 0, async (done: Function) => { + const flutterAbility: FlutterAbility = new FlutterAbility(); + const result = flutterAbility.getAppBundlePath(); + expect(result).assertEqual(""); + done(); + }) + + it('TestAttachToEngineAutomatically', 0, async (done: Function) => { + const flutterAbility: FlutterAbility = new FlutterAbility(); + const result = flutterAbility.attachToEngineAutomatically(); + expect(result).assertTrue(); + done(); + }) + + it('TestGetExclusiveAppComponent', 0, async (done: Function) => { + const flutterAbility: FlutterAbility = new FlutterAbility(); + const result = flutterAbility.getExclusiveAppComponent(); + expect(result).assertNull(); + done(); + }) + + it('TestGetFlutterEngine', 0, async (done: Function) => { + const flutterAbility: FlutterAbility = new FlutterAbility(); + const result = flutterAbility.getFlutterEngine(); + expect(result).assertNull(); + done(); + }) + }) + +} + +class TestFlutterPlugin implements FlutterPlugin { + getUniqueClassName(): string { + return "engine test"; + } + + onAttachedToEngine(binding: FlutterPluginBinding): void { + console.info("uitest: onAttachedToEngine"); + } + + onDetachedFromEngine(binding: FlutterPluginBinding): void { + console.info("uitest: onAttachedToEngine"); + } +} + +let plugin: FlutterPlugin = new TestFlutterPlugin(); diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterEntryTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterEntryTest.test.ets new file mode 100644 index 0000000000..5d9ba80399 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterEntryTest.test.ets @@ -0,0 +1,181 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import { FlutterEngine, FlutterPlugin, FlutterEntry } from "@ohos/flutter_ohos"; +import { FlutterPluginBinding } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin'; + +function sleep(time: number) { + return new Promise((resolve: Function) => setTimeout(resolve, time)); +} + +export default function FlutterEntryTest() { + describe('FlutterEntryTest', () => { + + it('TestGetFlutterView', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.getFlutterView(); + expect(result).assertNull(); + done(); + }) + + it('TestGetFlutterEngine', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.getFlutterEngine(); + expect(result).not().assertNull(); + done(); + }) + + it('TestShouldDispatchAppLifecycleState', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.shouldDispatchAppLifecycleState(); + expect(result).assertTrue(); + done(); + }) + + it('TestProvideFlutterEngine', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.provideFlutterEngine(getContext()); + expect(result).assertNull(); + done(); + }) + + it('TestProvidePlatformPlugin', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const flutterEngine = new FlutterEngine(getContext(), null, null, null); + const result = flutterEntry.providePlatformPlugin(flutterEngine); + expect(result).not().assertNull(); + done(); + }) + + it('TestGetFlutterShellArgs', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.getFlutterShellArgs(); + expect(result).not().assertNull(); + done(); + }) + + it('TestGetDartEntrypointArgs', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.getDartEntrypointArgs(); + expect(result).not().assertNull(); + done(); + }) + + it('TestPopSystemNavigator', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.popSystemNavigator(); + expect(result).assertFalse(); + done(); + }) + + it('TestShouldAttachEngineToAbility', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.shouldAttachEngineToAbility(); + expect(result).assertUndefined(); + done(); + }) + + it('TestGetDartEntrypointLibraryUri', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.getDartEntrypointLibraryUri(); + expect(result).assertEqual(""); + done(); + }) + + it('TestGetAppBundlePath', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.getAppBundlePath(); + expect(result).assertEqual(""); + done(); + }) + + it('TestGetDartEntrypointFunctionName', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.getDartEntrypointFunctionName(); + expect(result).not().assertNull(); + done(); + }) + + it('TestGetInitialRoute', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.getInitialRoute(); + expect(result).not().assertNull(); + done(); + }) + + it('TestAttachToEngineAutomatically', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.attachToEngineAutomatically(); + expect(result).assertTrue(); + done(); + }) + + it('TestShouldRestoreAndSaveState', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.shouldRestoreAndSaveState(); + expect(result).not().assertNull(); + done(); + }) + + it('TestGetExclusiveAppComponent', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.getExclusiveAppComponent(); + expect(result).assertNull(); + done(); + }) + + it('TestGetCachedEngineId', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.getCachedEngineId(); + expect(result).assertUndefined(); + done(); + }) + + it('TestGetCachedEngineGroupId', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + const result = flutterEntry.getCachedEngineGroupId(); + expect(result).assertUndefined(); + done(); + }) + + it('TestAddPlugin', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + flutterEntry.addPlugin(plugin); + done(); + }) + + it('TestRemovePlugin', 0, async (done: Function) => { + const flutterEntry: FlutterEntry = new FlutterEntry(getContext()); + flutterEntry.removePlugin(plugin); + done(); + }) + }) +} + +class TestFlutterPlugin implements FlutterPlugin { + getUniqueClassName(): string { + return "engine test"; + } + + onAttachedToEngine(binding: FlutterPluginBinding): void { + console.info("uitest: onAttachedToEngine"); + } + + onDetachedFromEngine(binding: FlutterPluginBinding): void { + console.info("uitest: onAttachedToEngine"); + } +} + +let plugin: FlutterPlugin = new TestFlutterPlugin(); diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterManagerTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterManagerTest.test.ets new file mode 100644 index 0000000000..3740524e87 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/FlutterManagerTest.test.ets @@ -0,0 +1,79 @@ +/* + * 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 { describe, it, expect, beforeAll } from '@ohos/hypium'; +import { FlutterManager } from "@ohos/flutter_ohos"; +import { window } from '@kit.ArkUI'; +import { FullScreenListener } from '@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterManager'; + +function sleep(time: number) { + return new Promise((resolve: Function) => setTimeout(resolve, time)); +} + +const flutterManager: FlutterManager = FlutterManager.getInstance(); +const uiAbility = flutterManager.getUIAbility(getContext()); + +export default function FlutterManagerTest() { + describe('FlutterManagerTest', () => { + beforeAll(async () => { + const windowStage = flutterManager.getWindowStage(uiAbility); + await sleep(1000); + flutterManager.pushWindowStage(uiAbility, windowStage); + await sleep(1000); + flutterManager.popWindowStage(uiAbility); + await sleep(1000); + flutterManager.pushUIAbility(uiAbility); + await sleep(1000); + flutterManager.popUIAbility(uiAbility); + + }) + + it('TestGetFlutterViewList', 0, async (done: Function) => { + const result = flutterManager.getFlutterViewList(); + expect(result).not().assertNull(); + done(); + }) + + it('TestSetFullScreenListener', 0, async (done: Function) => { + class MyFullScreenListener implements FullScreenListener { + useFullScreen(): boolean { + return true; + } + + setUseFullScreen(useFullScreen: boolean): void { + console.info("uitest: setUseFullScreen useFullScreen " + useFullScreen); + } + + onScreenStateChanged(data: window.WindowStatusType): void { + console.info("uitest: onScreenStateChanged"); + } + } + + const listener: FullScreenListener = new MyFullScreenListener(); + flutterManager.setFullScreenListener(listener); + await sleep(1000); + const result = flutterManager.getFullScreenListener(); + expect(result).not().assertNull(); + done(); + }) + + it('TestFullScreen', 0, async (done: Function) => { + const result = flutterManager.useFullScreen(); + expect(result).assertTrue(); + flutterManager.setUseFullScreen(result); + flutterManager.clear(); + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/SettingTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/SettingTest.test.ets new file mode 100644 index 0000000000..d9a0489034 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/SettingTest.test.ets @@ -0,0 +1,38 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import { Settings } from "@ohos/flutter_ohos"; +import { MediaQuery } from '@kit.ArkUI'; +import { PlatformBrightness } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/SettingsChannel'; + +const settings: Settings = new Settings(null); + +export default function SettingTest() { + describe('SettingTest', () => { + it('TestGetTextScaleFactor', 0, async (done: Function) => { + const result: number = settings.getTextScaleFactor(); + expect(result).not().assertNull(); + done(); + }) + + it('TestGetThemeMode', 0, async (done: Function) => { + const mediaQuery: MediaQuery = new MediaQuery(); + settings.sendSettings(mediaQuery); + const result: PlatformBrightness = settings.getThemeMode(mediaQuery); + expect(result).not().assertNull(); + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/TouchEventProcessorTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/TouchEventProcessorTest.test.ets new file mode 100644 index 0000000000..dc72a1450d --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/TouchEventProcessorTest.test.ets @@ -0,0 +1,41 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import TouchEventProcessor from '@ohos/flutter_ohos/src/main/ets/embedding/ohos/TouchEventProcessor'; +import { CustomTouchEvent } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/CustomTouchEvent'; + +export default function TouchEventProcessorTest() { + const touchEventProcessor: TouchEventProcessor = new TouchEventProcessor(); + + describe('TouchEventProcessorTest', () => { + + it('getInstance', 0, async (done: Function) => { + console.info("uitest: getInstance begin"); + const getInstance: TouchEventProcessor = TouchEventProcessor.getInstance(); + expect(getInstance).not().assertNull(); + done(); + }) + + it('decodeTouchPacket', 0, async (done: Function) => { + console.info("uitest: decodeTouchPacket begin"); + const strings = ['test1', 'test2', 'test3']; + const top = 10; + const left = 10; + const decodeTouchPacket: CustomTouchEvent = touchEventProcessor.constureCustomTouchEvent(strings, top, left); + expect(decodeTouchPacket).not().assertNull(); + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/TouchEventTrackerTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/TouchEventTrackerTest.test.ets new file mode 100644 index 0000000000..fc93b33e7b --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/TouchEventTrackerTest.test.ets @@ -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. + */ +import { describe, it, expect } from '@ohos/hypium'; +import { TouchEventId, TouchEventTracker } from '@ohos/flutter_ohos/src/main/ets/embedding/ohos/TouchEventTracker'; +import { TouchEvent } from '@ohos.multimodalInput.touchEvent'; + +export default function TouchEventTrackerTest() { + const touchEventTracker: TouchEventTracker = new TouchEventTracker(); + + describe('TouchEventTrackerTest', () => { + + it('getInstance', 0, async (done: Function) => { + console.info("uitest: getInstance begin"); + const getInstance: TouchEventTracker = TouchEventTracker.getInstance(); + expect(getInstance).not().assertNull(); + done(); + }) + + it('track', 0, async (done: Function) => { + console.info("uitest: decodeTouchPacket begin"); + const event: TouchEvent | null = null; + if(event) { + const decodeTouchPacket: TouchEventId = touchEventTracker.track(event); + expect(decodeTouchPacket).not().assertNull(); + } + done(); + }) + + it('pop', 0, async (done: Function) => { + console.info("uitest: pop begin"); + const eventId: TouchEventId | null = null; + if(eventId) { + const tuchEvent: TouchEvent = touchEventTracker.pop(eventId); + expect(tuchEvent).not().assertNull(); + } + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/WindowInfoRepositoryCallbackAdapterWrapperTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/WindowInfoRepositoryCallbackAdapterWrapperTest.test.ets new file mode 100644 index 0000000000..92a803725b --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/embedding/ohos/WindowInfoRepositoryCallbackAdapterWrapperTest.test.ets @@ -0,0 +1,29 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import WindowInfoRepositoryCallbackAdapterWrapper from '@ohos/flutter_ohos/src/main/ets/embedding/ohos/WindowInfoRepositoryCallbackAdapterWrapper'; + +export default function WindowInfoRepositoryCallbackAdapterWrapperTest() { + + describe('WindowInfoRepositoryCallbackAdapterWrapper', () => { + + it('WindowInfoRepositoryCallbackAdapterWrapper', 0, async (done: Function) => { + console.info("uitest: WindowInfoRepositoryCallbackAdapterWrapper begin"); + const windowInfoRepositoryCallbackAdapterWrapper: WindowInfoRepositoryCallbackAdapterWrapper = new WindowInfoRepositoryCallbackAdapterWrapper(); + expect(windowInfoRepositoryCallbackAdapterWrapper).not().assertNull(); + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/BinaryCodecTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/BinaryCodecTest.test.ets new file mode 100644 index 0000000000..cd1f7813dd --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/BinaryCodecTest.test.ets @@ -0,0 +1,37 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import { BinaryCodec } from "@ohos/flutter_ohos"; +import { buffer } from '@kit.ArkTS'; + +const binaryCodec: BinaryCodec = new BinaryCodec(true); + +export default function BinaryCodecTest() { + describe('BinaryCodecTest', () => { + it('TestBinaryCodecEncodeMessageSend', 0, async (done: Function) => { + let blobValue: buffer.Blob = new buffer.Blob(['name', 'age', 'sex']); + let message: ArrayBuffer = await blobValue.arrayBuffer(); + const result: ArrayBuffer = binaryCodec.encodeMessage(message); + expect(result).not().assertNull(); + done(); + }) + + it('TestBinaryCodecDecodeMessage', 0, async (done: Function) => { + const result = binaryCodec.decodeMessage(null); + expect(result).not().assertNull(); + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/BinaryMessengerTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/BinaryMessengerTest.test.ets new file mode 100644 index 0000000000..b746c79682 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/BinaryMessengerTest.test.ets @@ -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. + */ +import { describe, expect, it } from '@ohos/hypium'; +import { + BinaryMessageHandler, + BinaryMessenger, + BinaryReply, + TaskQueue, + TaskQueueOptions +} from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; + +export default function BinaryMessengerTest() { + let binaryMessenger: CurBinaryMessenger = new CurBinaryMessenger(); + + describe('BinaryMessengerTest', () => { + + it('makeBackgroundTaskQueue', 0, async (done: Function) => { + console.info("uitest: makeBackgroundTaskQueue begin"); + const options = new TaskQueueOptions(); + const taskQueue: TaskQueue = binaryMessenger.makeBackgroundTaskQueue(options); + expect(taskQueue).not().assertNull(); + done(); + }) + }) +} + +class CurBinaryMessenger implements BinaryMessenger { + makeBackgroundTaskQueue(options?: TaskQueueOptions | undefined): TaskQueue { + return {}; + } + + send(channel: String, message: ArrayBuffer, callback?: BinaryReply | null | undefined) { + + } + + setMessageHandler(channel: String, handler: BinaryMessageHandler | BinaryMessageHandler | null, taskQueue?: TaskQueue, + ...args: Object[]) { + } +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/FlutterException.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/FlutterException.test.ets new file mode 100644 index 0000000000..fbdeee4dbf --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/FlutterException.test.ets @@ -0,0 +1,58 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import FlutterException from '@ohos/flutter_ohos/src/main/ets/plugin/common/FlutterException'; + +interface keyValue { + key: string; +} + +interface anotherKey { + anotherKey: string; +} + +interface defaultKey { + defaultKey: string; +} + +export default function FlutterExceptionTest() { + describe('FlutterExceptionTest', () => { + it('should initialize with correct values', 0, () => { + const code = 'ERROR_CODE_123'; + const message = 'This is an error message'; + const details:keyValue = { key: 'value' }; + const exception = new FlutterException(code, message, details); + expect(exception.message).assertEqual(message); + expect(exception.code).assertEqual(code); + expect(exception.name).assertEqual(''); + }) + it('should have a stack property if provided', 0, () => { + const code = 'ERROR_CODE_456'; + const message = 'Another error message'; + const details: anotherKey = { anotherKey: 'anotherValue' }; + const stack = 'Error stack trace'; + const exception = new FlutterException(code, message, details); + exception.stack = stack; + expect(exception.stack).assertEqual(stack); + }) + it('should default name to an empty string if not provided', 0, () => { + const code = 'ERROR_CODE_789'; + const message = 'Default name test'; + const details: defaultKey = { defaultKey: 'defaultValue' }; + const exception = new FlutterException(code, message, details); + expect(exception.name).assertEqual(''); + }) + }) +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/JSONMessageCodec.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/JSONMessageCodec.test.ets new file mode 100644 index 0000000000..72e75a218e --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/JSONMessageCodec.test.ets @@ -0,0 +1,29 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import JSONMessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMessageCodec'; +import StringUtils from '@ohos/flutter_ohos/src/main/ets/util/StringUtils'; + +export default function JSONMessageCodecTest() { + describe('JSONMessageCodecTest', () => { + const codec = JSONMessageCodec.INSTANCE; + it('should encode and decode a null message', 0, () => { + const originalMessage = null; + const encodedMessage = codec.encodeMessage(originalMessage); + const decodedMessage = StringUtils.arrayBufferToString(encodedMessage); + expect(decodedMessage).assertEqual(""); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/JSONMethodCodec.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/JSONMethodCodec.test.ets new file mode 100644 index 0000000000..9e4a471e51 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/JSONMethodCodec.test.ets @@ -0,0 +1,57 @@ +/* + * 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 { Any, JSONMethodCodec, MethodCall } from "@ohos/flutter_ohos"; +import { describe, expect, it, MockKit, when } from "@ohos/hypium"; + +export default function JSONMethodCodecUnitTest() { + describe('JSONMethodCodec', () => { + it("JSONMethodCodec_encodeMethodCall", 0, encodeMethodCall); + + it("JSONMethodCodec_encodeSuccessEnvelope", 0, encodeSuccessEnvelope); + + it("JSONMethodCodec_decodeEnvelope", 0, decodeEnvelope); + + }) +} + +function encodeMethodCall() { + let mocker = new MockKit(); + let ob = JSONMethodCodec.INSTANCE; + let mockFunc = mocker.mockFunc(ob, ob.encodeMethodCall); + let params = new MethodCall("key", "value"); + let r = new ArrayBuffer(4096); + when(mockFunc)(params).afterReturn(r); + let result = ob.encodeMethodCall(params); + expect(result).assertEqual(r); +} + +function encodeSuccessEnvelope() { + let mocker = new MockKit(); + let ob = JSONMethodCodec.INSTANCE; + let mockFunc = mocker.mockFunc(ob, ob.encodeSuccessEnvelope); + let r = new ArrayBuffer(4096); + when(mockFunc)(null).afterReturn(r); + expect(ob.encodeSuccessEnvelope(null)).assertEqual(r); +} + +function decodeEnvelope() { + let mocker = new MockKit(); + let ob = JSONMethodCodec.INSTANCE; + let mockFunc = mocker.mockFunc(ob, ob.decodeEnvelope); + let r = new ArrayBuffer(4096); + when(mockFunc)(r).afterReturn("any"); + let result: Any = ob.decodeEnvelope(r); + expect(result).assertEqual("any"); +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/MethodCall.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/MethodCall.test.ets new file mode 100644 index 0000000000..0d69393e7d --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/MethodCall.test.ets @@ -0,0 +1,34 @@ +/* + * 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 { MethodCall } from "@ohos/flutter_ohos"; +import { describe, expect, it } from "@ohos/hypium"; + +export default function MethodCallUnitTest() { + describe('MethodCall', () => { + it("MethodCall_argument", 0, argument); + + it("MethodCall_hasArgument", 0, hasArgument); + }) +} + +function argument() { + let ob = new MethodCall("get", null); + expect(ob.argument("key")).assertNull(); +} + +function hasArgument() { + let ob = new MethodCall("get", null); + expect(ob.hasArgument("key")).assertFalse(); +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableBinaryCodec.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableBinaryCodec.test.ets new file mode 100644 index 0000000000..f8174e51fb --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableBinaryCodec.test.ets @@ -0,0 +1,37 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import { SendableBinaryCodec } from '@ohos/flutter_ohos'; +import { buffer } from '@kit.ArkTS'; + +export default function SendableBinaryCodecTest() { + describe('SendableBinaryCodecTest', () => { + it('encodeMessage', 0, async (done: Function) => { + let blobValue: buffer.Blob = new buffer.Blob(['name', 'age', 'sex']); + let message: ArrayBuffer = await blobValue.arrayBuffer(); + expect(SendableBinaryCodec.INSTANCE_DIRECT.encodeMessage(message)) + .not() + .assertNull(); + done(); + }) + + it('decodeMessage', 0, () => { + expect(SendableBinaryCodec.INSTANCE_DIRECT.decodeMessage(null)) + .not() + .assertNull(); + }); + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableJSONMessageCodec.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableJSONMessageCodec.test.ets new file mode 100644 index 0000000000..4ee7d40da6 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableJSONMessageCodec.test.ets @@ -0,0 +1,29 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import SendableJSONMessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/SendableJSONMessageCodec'; +import StringUtils from '@ohos/flutter_ohos/src/main/ets/util/StringUtils' + +export default function SendableJSONMessageCodecTest() { + describe('SendableJSONMessageCodecTest', () => { + const codec = SendableJSONMessageCodec.INSTANCE; + it('encodeMessage and decodeMessage with a null message', 0, () => { + const originalMessage = null; + const encodedMessage = codec.encodeMessage(originalMessage); + const decodedMessage = StringUtils.arrayBufferToString(encodedMessage); + expect(decodedMessage).assertEqual(""); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableJSONMethodCodec.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableJSONMethodCodec.test.ets new file mode 100644 index 0000000000..225ab226f0 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableJSONMethodCodec.test.ets @@ -0,0 +1,41 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import SendableJSONMethodCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/SendableJSONMethodCodec'; + +export default function SendableJSONMethodCodecTest() { + describe('SendableJSONMethodCodecTest', () => { + const codec = SendableJSONMethodCodec.INSTANCE; + it('throws an error for invalid JSON', 0, () => { + const invalidJSON = new ArrayBuffer(1); + + try { + codec.decodeMethodCall(invalidJSON); + //fail('Expected an error to be thrown'); + throw new Error('Expected an error to be thrown'); + } catch (e) { + expect(e.message).assertContain('Invalid JSON') + } + + try { + codec.decodeEnvelope(invalidJSON); + //fail('Expected an error to be thrown'); + throw new Error('Expected an error to be thrown'); + } catch (e) { + expect(e.message).assertContain('Invalid JSON') + } + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableStandardMessageCodec.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableStandardMessageCodec.test.ets new file mode 100644 index 0000000000..b86d5cfe1c --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableStandardMessageCodec.test.ets @@ -0,0 +1,88 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import Any from '@ohos/flutter_ohos/src/main/ets/plugin/common/Any'; +import SendableStandardMessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/SendableStandardMessageCodec'; + +export default function SendableStandardMessageCodecTest() { + describe('SendableStandardMessageCodecTest', () => { + const codec = SendableStandardMessageCodec.INSTANCE; + + it('testEncodeDecodeNull', 0, () => { + const encoded = codec.encodeMessage(null); + const decoded:Any = codec.decodeMessage(encoded); + expect(decoded).assertNull(); + }) + + it('testEncodeDecodeBoolean', 0, () => { + const encodedTrue = codec.encodeMessage(true); + const decodedTrue:Any = codec.decodeMessage(encodedTrue); + expect(decodedTrue).assertTrue(); + + const encodedFalse = codec.encodeMessage(false); + const decodedFalse:Any = codec.decodeMessage(encodedFalse); + expect(decodedFalse).assertFalse(); + }) + + it('testEncodeDecodeNumber', 0, () => { + const int32Value = 123456; + const encodedInt32 = codec.encodeMessage(int32Value); + const decodedInt32:Any = codec.decodeMessage(encodedInt32); + expect(decodedInt32).assertEqual(int32Value); + + const int64Value = BigInt(9007199254740991); // Max safe integer + const encodedInt64 = codec.encodeMessage(int64Value); + const decodedInt64:Any = codec.decodeMessage(encodedInt64); + expect(decodedInt64).assertEqual(int64Value); + + const float64Value = 3.14159; + const encodedFloat64 = codec.encodeMessage(float64Value); + const decodedFloat64:Any = codec.decodeMessage(encodedFloat64); + expect(decodedFloat64).assertClose(float64Value, 5); + + }) + + it('testEncodeDecodeUint8Array', 0, () => { + const uint8Array = new Uint8Array([1, 2, 3, 4, 5]); + const encodedArray = codec.encodeMessage(uint8Array); + const decodedArray:Any = codec.decodeMessage(encodedArray); + expect(decodedArray).assertDeepEquals(uint8Array); + }) + + it('testEncodeDecodeInt32Array', 0, () => { + const int32Array = new Int32Array([1, 2, 3, 4, 5]); + const encodedArray = codec.encodeMessage(int32Array); + const decodedArray:Any = codec.decodeMessage(encodedArray); + expect(decodedArray).assertDeepEquals(int32Array); + }) + + it('testEncodeDecodeBigInt64Array', 0, () => { + const bigInt64Array = new BigInt64Array([BigInt(1), BigInt(2), BigInt(3), BigInt(4), BigInt(5)]); + const encodedArray = codec.encodeMessage(bigInt64Array); + const decodedArray:Any = codec.decodeMessage(encodedArray); + expect(decodedArray.length).assertEqual(bigInt64Array.length); + for (let i = 0; i < bigInt64Array.length; i++) { + expect(decodedArray[i]).assertEqual(bigInt64Array[i]); + } + }) + + it('testEncodeDecodeFloat64Array', 0, () => { + const float64Array = new Float64Array([1.1, 2.2, 3.3, 4.4, 5.5]); + const encodedArray = codec.encodeMessage(float64Array); + const decodedArray:Any = codec.decodeMessage(encodedArray); + expect(decodedArray).assertDeepEquals(float64Array); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableStandardMethodCodec.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableStandardMethodCodec.test.ets new file mode 100644 index 0000000000..7257b488ba --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableStandardMethodCodec.test.ets @@ -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. + */ +import { describe, it, expect } from '@ohos/hypium'; +import SendableStandardMethodCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/SendableStandardMethodCodec'; + +export default function SendableStandardMethodCodecTest() { + describe('SendableStandardMethodCodecTest', () => { + const codec = SendableStandardMethodCodec.INSTANCE; + it('decodeMethodCall_shouldThrowErrorOnCorruptedMethodCall', 0, () => { + const corruptedBuffer = new ArrayBuffer(2); + const bufferView = new Uint8Array(corruptedBuffer); + bufferView[0] = 0; + bufferView[1] = 1; + + try { + codec.decodeMethodCall(corruptedBuffer); + expect(false).assertEqual(true); + } catch (e) { + expect(e.message).assertEqual('Method call corrupted'); + } + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableStringCodec.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableStringCodec.test.ets new file mode 100644 index 0000000000..7a5d4a3b8b --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/SendableStringCodec.test.ets @@ -0,0 +1,43 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import StringCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/SendableStringCodec' +import StringUtils from '@ohos/flutter_ohos/src/main/ets/util/StringUtils' + +export default function SendableStringCodecTest() { + describe('SendableStringCodecTest', () => { + const codec = StringCodec.INSTANCE; + it('encodeMessage_emptyString_ReturnEmptyString', 0, () => { + const testString = ""; + const encodedMessage = codec.encodeMessage(testString); + const decodedString = StringUtils.arrayBufferToString(encodedMessage); + expect(decodedString).assertEqual(testString); + }) + it('encodeMessage_null_ReturnEmptyString', 0, () => { + const encodedMessage = codec.encodeMessage(""); + const decodedString = StringUtils.arrayBufferToString(encodedMessage); + expect(decodedString).assertEqual(""); + }) + it('decodeMessage_emptyString_ReturnEmptyString', 0, () => { + const encodedMessage = new ArrayBuffer(0); + const decodedString = codec.decodeMessage(encodedMessage); + expect(decodedString).assertEqual(""); + }) + it('decodeMessage_null_ReturnEmptyString', 0, () => { + const decodedString = codec.decodeMessage(null); + expect(decodedString).assertEqual(""); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/StandardMessageCodec.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/StandardMessageCodec.test.ets new file mode 100644 index 0000000000..21ce334f79 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/StandardMessageCodec.test.ets @@ -0,0 +1,92 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import Any from '@ohos/flutter_ohos/src/main/ets/plugin/common/Any'; +import StandardMessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec'; + +export default function StandardMessageCodecTest() { + describe('StandardMessageCodecTest', () => { + const codec = StandardMessageCodec.INSTANCE; + it('should encode and decode null', 0, () => { + const encoded = codec.encodeMessage(null); + const decoded:Any = codec.decodeMessage(encoded); + expect(decoded).assertNull(); + }) + it('should encode and decode boolean', 0, () => { + const encodedTrue = codec.encodeMessage(true); + const decodedTrue:Any = codec.decodeMessage(encodedTrue); + expect(decodedTrue).assertTrue(); + + const encodedFalse = codec.encodeMessage(false); + const decodedFalse:Any = codec.decodeMessage(encodedFalse); + expect(decodedFalse).assertFalse(); + }) + it('should encode and decode number (int32)', 0, () => { + const number = 123456; + const encoded = codec.encodeMessage(number); + const decoded:Any = codec.decodeMessage(encoded); + expect(decoded).assertEqual(number); + }) + it('should encode and decode number (int64)', 0, () => { + const number = BigInt(1234567890123456789); + const encoded = codec.encodeMessage(number); + const decoded:Any = codec.decodeMessage(encoded); + expect(decoded).assertEqual(number); + }) + it('should encode and decode number (float64)', 0, ()=> { + const number = 3.14159;; + const encoded = codec.encodeMessage(number); + const decoded:Any = codec.decodeMessage(encoded); + expect(decoded).assertClose(number,5) + }) + it('should encode and decode Uint8Array', 0, () => { + const array = new Uint8Array([1, 2, 3, 4, 5]); + const encoded = codec.encodeMessage(array); + const decoded:Any = codec.decodeMessage(encoded); + expect(decoded).assertDeepEquals(array); + }) + it('should encode and decode Int32Array', 0, () => { + const array = new Int32Array([1, 2, 3, 4, 5]); + const encoded = codec.encodeMessage(array); + const decoded:Any = codec.decodeMessage(encoded); + expect(decoded).assertDeepEquals(array); + }) + it('should encode and decode BigInt64Array', 0, () => { + const array = new BigInt64Array([BigInt(1), BigInt(2), BigInt(3), BigInt(4), BigInt(5)]); + const encoded = codec.encodeMessage(array); + const decoded:Any = codec.decodeMessage(encoded); + expect(decoded.length).assertEqual(array.length); + for (let i = 0; i < array.length; i++) { + expect(decoded[i]).assertEqual(array[i]); + } + }) + it('should encode and decode Float32Array', 0, () => { + const array = new Float32Array([1.1, 2.2, 3.3, 4.4, 5.5]); + const encoded = codec.encodeMessage(array); + const decoded:Any = codec.decodeMessage(encoded); + for (let i = 0; i < array.length; i++) { + expect(decoded[i]).assertEqual(array[i]); + } + }) + it('should encode and decode Float64Array', 0, () => { + const array = new Float64Array([1.1, 2.2, 3.3, 4.4, 5.5]); + const encoded = codec.encodeMessage(array); + const decoded:Any = codec.decodeMessage(encoded); + for (let i = 0; i < array.length; i++) { + expect(decoded[i]).assertEqual(array[i]); + } + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/StandardMethodCodec.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/StandardMethodCodec.test.ets new file mode 100644 index 0000000000..034ddafc1f --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/StandardMethodCodec.test.ets @@ -0,0 +1,32 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import StandardMethodCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec'; + +export default function StandardMethodCodecTest() { + describe('StandardMethodCodecTest', () => { + const codec = StandardMethodCodec.INSTANCE; + it('should throw an error for a corrupted method call', 0, () => { + const corruptedMethodCall = new ArrayBuffer(2); // Just an invalid ArrayBuffer + try { + codec.decodeMethodCall(corruptedMethodCall); + //fail('Expected an error to be thrown'); + throw new Error('Expected an error to be thrown'); + } catch (e) { + expect(e.message).assertEqual('Method call corrupted'); + } + }); + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/StringCodec.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/StringCodec.test.ets new file mode 100644 index 0000000000..74780cd085 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/common/StringCodec.test.ets @@ -0,0 +1,38 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import StringCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StringCodec' +import StringUtils from '@ohos/flutter_ohos/src/main/ets/util/StringUtils' + +export default function StringCodecTest() { + describe('StringCodecTest', () => { + const codec = StringCodec.INSTANCE; + it('encodeMessage_emptyString_ReturnEmptyString', 0, () => { + const testString = ""; + const encodedMessage = codec.encodeMessage(testString); + const decodedString = StringUtils.arrayBufferToString(encodedMessage); + expect(decodedString).assertEqual(testString); + }) + it('decodeMessage_emptyString_ReturnEmptyString', 0, () => { + const encodedMessage = new ArrayBuffer(0); + const decodedString = codec.decodeMessage(encodedMessage); + expect(decodedString).assertEqual(""); + }) + it('decodeMessage_null_ReturnEmptyString', 0, () => { + const decodedString = codec.decodeMessage(null); + expect(decodedString).assertEqual(""); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/editing/ListenableEditingState.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/editing/ListenableEditingState.test.ets new file mode 100644 index 0000000000..1c6f9e070a --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/editing/ListenableEditingState.test.ets @@ -0,0 +1,48 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import { EditingStateWatcher, ListenableEditingState } from '@ohos/flutter_ohos/src/main/ets/plugin/editing/ListenableEditingState'; + +export default function ListenableEditingStateTest() { + describe('ListenableEditingStateTest', () => { + let editingState: ListenableEditingState = new ListenableEditingState(null, 0); + it('should initialize with default values', 0, () => { + expect(editingState.getSelectionStart()).assertEqual(0); + expect(editingState.getSelectionEnd()).assertEqual(0); + expect(editingState.getComposingStart()).assertEqual(-1); + expect(editingState.getComposingEnd()).assertEqual(-1); + expect(editingState.getStringCache()).assertEqual(''); + }) + it('should handle insert text event correctly', 0, () => { + editingState.handleInsertTextEvent('hello'); + expect(editingState.getStringCache()).assertEqual('hello'); + expect(editingState.getSelectionStart()).assertEqual(5); + expect(editingState.getSelectionEnd()).assertEqual(5); + }) + + it('should handle delete event correctly (right)', 0, () => { + editingState.handleDeleteEvent(true, 1); + expect(editingState.getStringCache()).assertEqual('hello'); + expect(editingState.getSelectionStart()).assertEqual(5); + expect(editingState.getSelectionEnd()).assertEqual(5); + }) + it('should handle newline event correctly', 0, () => { + editingState.handleNewlineEvent(); + expect(editingState.getStringCache()).assertEqual('hello\n'); + expect(editingState.getSelectionStart()).assertEqual(6); + expect(editingState.getSelectionEnd()).assertEqual(6); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/editing/TextEditingDelta.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/editing/TextEditingDelta.test.ets new file mode 100644 index 0000000000..418797d0ea --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/editing/TextEditingDelta.test.ets @@ -0,0 +1,33 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import { TextEditingDelta } from '@ohos/flutter_ohos/src/main/ets/plugin/editing/TextEditingDelta'; + +export default function TextEditingDeltaTest() { + describe('TextEditingDeltaTest', () => { + it('testToJSON', 0, () => { + const delta = new TextEditingDelta("Old Text", 0, 0, 0, 0, 2, 5, "Delta Text"); + const json = delta.toJSON(); + expect(json.oldText).assertEqual("Old Text"); + expect(json.deltaText).assertEqual("Delta Text"); + expect(json.deltaStart).assertEqual(2); + expect(json.deltaEnd).assertEqual(5); + expect(json.selectionBase).assertEqual(0); + expect(json.selectionExtent).assertEqual(0); + expect(json.composingBase).assertEqual(0); + expect(json.composingExtent).assertEqual(0); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/editing/TextInputPlugin.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/editing/TextInputPlugin.test.ets new file mode 100644 index 0000000000..eb05ddadc5 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/editing/TextInputPlugin.test.ets @@ -0,0 +1,46 @@ +/* + * 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 { describe, beforeEach, it, expect } from '@ohos/hypium' +import TextInputChannel from '@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/TextInputChannel'; +import TextInputPlugin from '@ohos/flutter_ohos/src/main/ets/plugin/editing/TextInputPlugin'; +import TextInputMethodHandlerImpl from '@ohos/flutter_ohos/src/main/ets/plugin/editing/TextInputPlugin'; +import common from '@ohos.app.ability.common'; +import DartExecutor from '@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartExecutor'; +import FlutterInjector from '@ohos/flutter_ohos/src/main/ets/FlutterInjector'; + +export default function TextInputPluginTest() { + describe('TextInputPluginTest', () => { + let textInputPlugin: TextInputPlugin; + let textInputChannelMock: TextInputChannel; + let textInputMethodHandlerImpl: TextInputMethodHandlerImpl; + let dartExecutor: DartExecutor; + beforeEach(() => { + let context: common.Context = getContext(); + const assetManager = context.resourceManager; + const flutterNapi = FlutterInjector.getInstance().getFlutterNapi(); + dartExecutor = new DartExecutor(flutterNapi, assetManager); + textInputChannelMock = new TextInputChannel(dartExecutor); + textInputPlugin = new TextInputPlugin(textInputChannelMock); + textInputMethodHandlerImpl = new TextInputMethodHandlerImpl(textInputChannelMock); + }) + it('should initialize correctly', 0, ()=> { + expect(textInputMethodHandlerImpl).not().assertNull(); + }) + it('Test clearTextInputClient', 0, () => { + textInputPlugin.clearTextInputClient(); + expect(textInputPlugin).not().assertNull(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/localization/LocalizationPlugin.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/localization/LocalizationPlugin.test.ets new file mode 100644 index 0000000000..b8b5f8f9f0 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/localization/LocalizationPlugin.test.ets @@ -0,0 +1,55 @@ +/* + * 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 { describe, beforeEach, it, expect } from '@ohos/hypium'; +import LocalizationPlugin from '@ohos/flutter_ohos/src/main/ets/plugin/localization/LocalizationPlugin'; +import common from '@ohos.app.ability.common'; +import LocalizationChannel,{LocalizationMessageHandler} from '@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/LocalizationChannel'; +import intl from '@ohos.intl'; +import DartExecutor from '@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartExecutor'; +import FlutterInjector from '@ohos/flutter_ohos/src/main/ets/FlutterInjector'; +import Any from '@ohos/flutter_ohos/src/main/ets/plugin/common/Any'; + +export default function LocalizationPluginTest() { + describe('LocalizationPluginTest', () => { + let localizationChannel: LocalizationChannel; + let localizationPlugin: LocalizationPlugin; + let dartExecutor: DartExecutor; + + beforeEach(() => { + let context: common.Context = getContext(); + const assetManager = context.resourceManager; + const flutterNapi = FlutterInjector.getInstance().getFlutterNapi(); + dartExecutor = new DartExecutor(flutterNapi, assetManager); + localizationChannel = new LocalizationChannel(dartExecutor); // 初始化LocalizationChannel + localizationPlugin = new LocalizationPlugin(context, localizationChannel); + }); + it('test_localeFromString', 0, () => { + let localeString = "zh_CN"; + let expectedLocale = new intl.Locale("zh_CN"); + let actualLocale = localizationPlugin.localeFromString(localeString); + + expect(actualLocale.language).assertEqual(expectedLocale.language); + expect(actualLocale.region).assertEqual(expectedLocale.region); + expect(actualLocale.script).assertEqual(expectedLocale.script); + }) + it('testSendLocaleToFlutter', 0, () => { + let mockSystemLocale = 'zh-Hans-AL'; + (localizationChannel as Any).sendLocales = (locales:Any) => { + expect(locales).assertContain(mockSystemLocale); + }; + localizationPlugin.sendLocaleToFlutter(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/AccessibilityEventsDelegate.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/AccessibilityEventsDelegate.test.ets new file mode 100644 index 0000000000..847ec183b7 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/AccessibilityEventsDelegate.test.ets @@ -0,0 +1,36 @@ +/* + * 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 { AccessibilityBridge, AccessibilityEventsDelegate } from "@ohos/flutter_ohos"; +import { describe, expect, it } from "@ohos/hypium"; + +export default function AccessibilityEventsDelegateUnitTest() { + describe('AccessibilityEventsDelegate', () => { + it("AccessibilityEventsDelegate_requestSendAccessibilityEvent", 0, requestSendAccessibilityEvent); + + it("AccessibilityEventsDelegate_onAccessibilityHoverEvent", 0, onAccessibilityHoverEvent); + }) +} + +function requestSendAccessibilityEvent() { + let delegate = new AccessibilityEventsDelegate(); + let result = delegate.requestSendAccessibilityEvent(new AccessibilityBridge()); + expect(result).assertTrue(); +} + +function onAccessibilityHoverEvent() { + let delegate = new AccessibilityEventsDelegate(); + let result = delegate.onAccessibilityHoverEvent(new AccessibilityBridge()); + expect(result).assertTrue(); +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformOverlayView.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformOverlayView.test.ets new file mode 100644 index 0000000000..4ddd8fe65f --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformOverlayView.test.ets @@ -0,0 +1,32 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import { AccessibilityEventsDelegate, PlatformOverlayView } from '@ohos/flutter_ohos'; + +const platformOverlayView: PlatformOverlayView = + new PlatformOverlayView(getContext(), 800, 800, new AccessibilityEventsDelegate()) + +export default function PlatformOverlayViewTest() { + describe('PlatformOverlayViewTest', () => { + it('PlatformOverlayView', 0, () => { + let overlayLayerViews = new Map(); + expect(overlayLayerViews).not().assertNull(); + }); + it('onHoverEvent', 0, () => { + expect(platformOverlayView.onHoverEvent()).assertFalse(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformView.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformView.test.ets new file mode 100644 index 0000000000..4369f8d25f --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformView.test.ets @@ -0,0 +1,37 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import { PlatformView } from '@ohos/flutter_ohos'; +import { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView'; + +export default function PlatformViewTest() { + describe('PlatformViewTest', () => { + class TestPlatformView extends PlatformView { + getView(): WrappedBuilder<[Params]> { + throw new Error('Method not implemented.'); + } + + dispose(): void { + throw new Error('Method not implemented.'); + } + } + + const platformView: PlatformView = new TestPlatformView() + it('getType', 0, () => { + expect(platformView.getType()).assertEqual('default') + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformViewRegistryImplTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformViewRegistryImplTest.test.ets new file mode 100644 index 0000000000..deaca608fc --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformViewRegistryImplTest.test.ets @@ -0,0 +1,36 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import { PlatformViewRegistryImpl, PlatformViewFactory } from "@ohos/flutter_ohos"; + +const platformViewRegistryImpl: PlatformViewRegistryImpl = new PlatformViewRegistryImpl(); + +export default function PlatformViewRegistryImplTest() { + describe('PlatformViewRegistryImplTest', () => { + it('TestPlatformViewRegistryImplGetFactory', 0, async (done: Function) => { + const platformViewFactory: PlatformViewFactory = platformViewRegistryImpl.getFactory('test'); + expect(platformViewFactory).not().assertNull(); + done(); + }) + + it('TestPlatformViewRegistryImplRegisterViewFactory', 0, async (done: Function) => { + const platformViewFactory: PlatformViewFactory = platformViewRegistryImpl.getFactory('test'); + expect(platformViewFactory).not().assertNull(); + const result = platformViewRegistryImpl.registerViewFactory('test', platformViewFactory); + expect(result).assertTrue(); + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformViewWrapperTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformViewWrapperTest.test.ets new file mode 100644 index 0000000000..2926252aeb --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformViewWrapperTest.test.ets @@ -0,0 +1,41 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import { PlatformViewWrapper, OhosTouchProcessor } from "@ohos/flutter_ohos"; +import { DVModel, DVModelParameters } from '@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView'; + +function sleep(time: number) { + return new Promise((resolve: Function) => setTimeout(resolve, time)); +} + +const platformViewWrapper: PlatformViewWrapper = new PlatformViewWrapper(); + +export default function PlatformViewWrapperTest() { + describe('PlatformViewWrapperTest', () => { + it('TestPlatformViewWrapperDvModel', 0, async (done: Function) => { + const newTouchProcessor: OhosTouchProcessor = new OhosTouchProcessor(); + platformViewWrapper.setTouchProcessor(newTouchProcessor); + await sleep(1000); + const dvModel: DVModel = platformViewWrapper.getDvModel(); + expect(dvModel).not().assertNull(); + await sleep(1000); + platformViewWrapper.addDvModel(dvModel); + await sleep(1000); + const parameters: DVModelParameters = new DVModelParameters(); + platformViewWrapper.setLayoutParams(parameters); + done(); + }) + }) +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformViewsControllerTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformViewsControllerTest.test.ets new file mode 100644 index 0000000000..7bbe3eef5d --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/PlatformViewsControllerTest.test.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 { describe, it, expect } from '@ohos/hypium'; +import { + PlatformViewsController, + FlutterOverlaySurface, +} from "@ohos/flutter_ohos"; + +const platformViewsController: PlatformViewsController = new PlatformViewsController(); +const direction: Direction = 100; + +export default function PlatformViewsControllerTest() { + describe('PlatformViewsControllerTest', () => { + + it('TestPlatformViewRegistryImplGetRegistry', 0, async (done: Function) => { + const result = platformViewsController.getRegistry(); + expect(result).not().assertNull(); + done(); + }) + + it('TestCreateOverlaySurface', 0, async (done: Function) => { + const result: FlutterOverlaySurface = platformViewsController.createOverlaySurface(); + expect(result).not().assertNull(); + done(); + }) + it('TestPlatformViewRegistryImplValidateDirection', 0, async (done: Function) => { + const result = platformViewsController.validateDirection(direction); + expect(result).assertFalse(); + done(); + }) + + it('TestPlatformViewRegistryImplGetFlutterView', 0, async (done: Function) => { + const result = platformViewsController.getFlutterView(); + expect(result).assertNull(); + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/RawPointerCoordTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/RawPointerCoordTest.test.ets new file mode 100644 index 0000000000..c26c4ee7f2 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/RawPointerCoordTest.test.ets @@ -0,0 +1,44 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import { RawPointerCoords } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/RawPointerCoord'; + +const orientation: number = 100; +const pressure: number = 100; +const size: number = 100; +const toolMajor: number = 100; +const toolMinor: number = 100; +const touchMajor: number = 100; +const touchMinor: number = 100; +const x: number = 100; +const y: number = 100; +const rawPointerCoords: RawPointerCoords = + new RawPointerCoords(orientation, pressure, size, toolMajor, toolMinor, touchMajor, touchMinor, x, y); + +export default function RawPointerCoordsTest() { + describe('RawPointerCoordsTest', () => { + it('TestRawPointerCoordsGetX', 0, async (done: Function) => { + const pointX = rawPointerCoords.getX(); + expect(pointX).not().assertNull(); + done(); + }) + + it('TestRawPointerCoordsGetY', 0, async (done: Function) => { + const pointY = rawPointerCoords.getY(); + expect(pointY).not().assertNull(); + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/RootDvModelManagerTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/RootDvModelManagerTest.test.ets new file mode 100644 index 0000000000..3bc489d587 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/platform/RootDvModelManagerTest.test.ets @@ -0,0 +1,36 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium'; +import { PlatformViewWrapper } from '@ohos/flutter_ohos'; +import { RootDvModeManager } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/RootDvModelManager'; +import { DVModel, DVModelContainer } from '@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView'; + +export default function DVModelContainerTest() { + describe('DVModelContainerTest', () => { + it('TestDVModelContainerGetRootDvMode', 0, async (done: Function) => { + const dvModel: DVModelContainer = RootDvModeManager.getRootDvMode(); + expect(dvModel).not().assertNull(); + done(); + }) + + it('TestDVModelAddDvModel', 0, async (done: Function) => { + const platformViewWrapper: PlatformViewWrapper = new PlatformViewWrapper(); + const dvModel: DVModel = platformViewWrapper.getDvModel(); + RootDvModeManager.addDvModel(dvModel); + expect(dvModel).not().assertNull(); + done(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/ByteBufferTest.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/ByteBufferTest.test.ets new file mode 100644 index 0000000000..536a5aed71 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/ByteBufferTest.test.ets @@ -0,0 +1,317 @@ +/* + * 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 { describe, it, expect, afterAll } from '@ohos/hypium'; +import { ByteBuffer } from "@ohos/flutter_ohos"; +import { buffer } from '@kit.ArkTS'; + +let byteBuffer: ByteBuffer; +let byteOffset: number; + +export default function ByteBufferTest() { + describe('ByteBufferTest', () => { + it('TestByteBufferFrom', 0, async (done: Function) => { + const blobValue: buffer.Blob = new buffer.Blob(['name', 'age', 'sex']); + const message: ArrayBuffer = await blobValue.arrayBuffer(); + const result = ByteBuffer.from(message); + expect(result.byteLength).assertEqual(10); + done(); + }) + + it('TestByteBufferByteOffset', 0, async (done: Function) => { + const blobValue: buffer.Blob = new buffer.Blob(['name', 'age', 'sex']); + const message: ArrayBuffer = await blobValue.arrayBuffer(); + byteBuffer = ByteBuffer.from(message); + byteOffset = byteBuffer.byteOffset; + expect(byteOffset).assertEqual(0); + done(); + }) + + it('TestByteBufferByteLength', 0, async (done: Function) => { + const result = byteBuffer.byteLength; + expect(result).assertEqual(10); + done(); + }) + + it('TestByteBufferBytesRemaining', 0, async (done: Function) => { + const result = byteBuffer.bytesRemaining; + expect(result).assertEqual(10); + done(); + }) + + it('TestByteBufferBuffer', 0, async (done: Function) => { + const result = byteBuffer.buffer; + expect(result).assertInstanceOf('ArrayBuffer'); + done(); + }) + + it('TestByteBufferHasRemaining', 0, async (done: Function) => { + const result = byteBuffer.hasRemaining(); + expect(result).assertTrue(); + done(); + }) + + it('TestByteBufferSkip', 0, async (done: Function) => { + const result = byteBuffer.byteLength; + expect(result).assertEqual(10); + byteBuffer.skip(result); + byteBuffer.checkWriteCapacity(10); + done(); + }) + + it('TestByteBufferGetBool', 0, async (done: Function) => { + byteBuffer.setBool(byteOffset, true); + let result = byteBuffer.getBool(byteOffset); + expect(result).assertTrue(); + done(); + }) + + it('TestByteBufferReadBool', 0, async (done: Function) => { + byteBuffer.writeBool(false); + let result = byteBuffer.readBool(); + expect(result).assertFalse(); + done(); + }) + + it('TestByteBufferGetInt8', 0, async (done: Function) => { + byteBuffer.setInt8(byteOffset, 10); + let result = byteBuffer.getInt8(byteOffset); + expect(result).assertEqual(10); + done(); + }) + + it('TestByteBufferReadInt8', 0, async (done: Function) => { + byteBuffer.writeInt8(byteOffset); + let result = byteBuffer.readInt8(); + expect(result).assertEqual(0); + done(); + }) + + it('TestByteBufferGetUint8', 0, async (done: Function) => { + byteBuffer.setUint8(byteOffset, 10); + let result = byteBuffer.getUint8(byteOffset); + expect(result).assertEqual(10); + done(); + }) + + it('TestByteBufferReadUint8', 0, async (done: Function) => { + byteBuffer.writeUint8(byteOffset); + let result = byteBuffer.readUint8(); + expect(result).assertEqual(0); + done(); + }) + + it('TestByteBufferGetInt16', 0, async (done: Function) => { + byteBuffer.setInt16(byteOffset, 10); + let result = byteBuffer.getInt16(byteOffset); + expect(result).assertEqual(10); + done(); + }) + + it('TestByteBufferReadInt16', 0, async (done: Function) => { + byteBuffer.writeInt16(byteOffset); + let result = byteBuffer.readInt16(); + expect(result).assertEqual(0); + done(); + }) + + it('TestByteBufferGetUint16', 0, async (done: Function) => { + byteBuffer.setUint16(byteOffset, 10); + let result = byteBuffer.getUint16(byteOffset); + expect(result).assertEqual(10); + done(); + }) + + it('TestByteBufferReadUint16', 0, async (done: Function) => { + byteBuffer.writeUint16(byteOffset); + let result = byteBuffer.readUint16(); + expect(result).assertEqual(0); + done(); + }) + + it('TestByteBufferGetInt32', 0, async (done: Function) => { + byteBuffer.setInt32(byteOffset, 10); + let result = byteBuffer.getInt32(byteOffset); + expect(result).assertEqual(10); + done(); + }) + + it('TestByteBufferReadInt32', 0, async (done: Function) => { + byteBuffer.writeInt32(byteOffset); + let result = byteBuffer.readInt32(); + expect(result).assertEqual(0); + done(); + }) + + it('TestByteBufferGetUint32', 0, async (done: Function) => { + byteBuffer.setUint32(byteOffset, 10); + let result = byteBuffer.getUint32(byteOffset); + expect(result).assertEqual(10); + done(); + }) + + it('TestByteBufferReadUint32', 0, async (done: Function) => { + byteBuffer.writeUint32(byteOffset); + let result = byteBuffer.readUint32(); + expect(result).assertEqual(0); + done(); + }) + + it('TestByteBufferGetFloat32', 0, async (done: Function) => { + byteBuffer.setFloat32(byteOffset, 10); + let result = byteBuffer.getFloat32(byteOffset); + expect(result).assertEqual(10); + done(); + }) + + it('TestByteBufferReadFloat32', 0, async (done: Function) => { + byteBuffer.writeFloat32(byteOffset); + let result = byteBuffer.readFloat32(); + expect(result).assertEqual(0); + done(); + }) + + it('TestByteBufferGetFloat64', 0, async (done: Function) => { + byteBuffer.setFloat64(byteOffset, 10); + let result = byteBuffer.getFloat64(byteOffset); + expect(result).assertEqual(10); + done(); + }) + + it('TestByteBufferReadFloat64', 0, async (done: Function) => { + byteBuffer.writeFloat64(byteOffset); + let result = byteBuffer.readFloat64(); + expect(result).assertEqual(0); + done(); + }) + + it('TestByteBufferGetBigInt64', 0, async (done: Function) => { + const value: bigint = BigInt(9223372036854775807); + byteBuffer.setBigInt64(byteOffset, value); + let result = byteBuffer.getBigInt64(byteOffset); + expect(result).not().assertNull(); + done(); + }) + + it('TestByteBufferReadBigInt64', 0, async (done: Function) => { + const value: bigint = BigInt(9223372036854775807); + byteBuffer.writeBigInt64(value); + let result = byteBuffer.readBigInt64(); + expect(result).assertEqual(0n); + done(); + }) + + it('TestByteBufferGetBigUint64', 0, async (done: Function) => { + const value: bigint = BigInt(9223372036854775807); + byteBuffer.setBigUint64(byteOffset, value); + let result = byteBuffer.getBigUint64(byteOffset); + expect(result).not().assertNull(); + done(); + }) + + it('TestByteBufferReadBigUint64', 0, async (done: Function) => { + const value: bigint = BigInt(9223372036854775807); + byteBuffer.writeBigUint64(value); + let result = byteBuffer.readBigUint64(); + expect(result).assertEqual(0n); + done(); + }) + + it('TestByteBufferGetInt64', 0, async (done: Function) => { + byteBuffer.setInt64(byteOffset, 10); + let result = byteBuffer.getInt64(byteOffset); + expect(result).assertEqual(10n); + done(); + }) + + it('TestByteBufferReadInt64', 0, async (done: Function) => { + byteBuffer.writeInt64(10); + let result = byteBuffer.readInt64(); + expect(result).assertEqual(0n); + done(); + }) + + it('TestByteBufferGetUint64', 0, async (done: Function) => { + byteBuffer.setUint64(byteOffset, 10); + let result = byteBuffer.getUint64(byteOffset); + expect(result).assertEqual(10); + done(); + }) + + it('TestByteBufferReadUint64', 0, async (done: Function) => { + byteBuffer.writeUint64(10); + let result = byteBuffer.readUint64(); + expect(result).assertEqual(0); + done(); + }) + + it('TestByteBufferGetUint8Array', 0, async (done: Function) => { + const value: Uint8Array = new Uint8Array(); + byteBuffer.setUint8Array(byteOffset, value); + let result = byteBuffer.getUint8Array(byteOffset); + expect(result).assertInstanceOf('Uint8Array'); + done(); + }) + + it('TestByteBufferReadUint8Array', 0, async (done: Function) => { + const value: Uint8Array = new Uint8Array(); + byteBuffer.writeUint8Array(value); + let result = byteBuffer.readUint8Array(); + expect(result).assertInstanceOf('Uint8Array'); + done(); + }) + + it('TestByteBufferGetUint16Array', 0, async (done: Function) => { + const value: Uint16Array = new Uint16Array(); + byteBuffer.setUint16Array(byteOffset, value); + let result = byteBuffer.getUint16Array(byteOffset); + expect(result).assertInstanceOf('Uint16Array'); + done(); + }) + + it('TestByteBufferReadUint16Array', 0, async (done: Function) => { + const value: Uint16Array = new Uint16Array(); + byteBuffer.writeUint16Array(value); + let result = byteBuffer.readUint16Array(); + expect(result).assertInstanceOf('Uint16Array'); + done(); + }) + + it('TestByteBufferGetString', 0, async (done: Function) => { + byteBuffer.setString(byteOffset, 'test'); + let result = byteBuffer.getString(byteOffset); + expect(result).not().assertNull(); + done(); + }) + + it('TestByteBufferReadString', 0, async (done: Function) => { + byteBuffer.writeString('test'); + let result = byteBuffer.readString(); + expect(result).assertUndefined(); + done(); + }) + + it('TestByteBufferToString', 0, async (done: Function) => { + let result = byteBuffer.toString(); + expect(result).not().assertNull(); + done(); + }) + + afterAll(() => { + byteBuffer.reset(); + byteBuffer.clear(); + }) + }) + +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/Log.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/Log.test.ets new file mode 100644 index 0000000000..5ef0a0618a --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/Log.test.ets @@ -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. + */ + +import { describe, it, expect } from '@ohos/hypium' +import { Log } from '@ohos/flutter_ohos'; + +export default function LogTest() { + describe('LogTest', () => { + it('Log', 0, () => { + expect(Log.toString()).not().assertNull(); + }); + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/MessageChannelUtils.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/MessageChannelUtils.test.ets new file mode 100644 index 0000000000..60c39c1c12 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/MessageChannelUtils.test.ets @@ -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. + */ + +import { describe, it, expect } from '@ohos/hypium' +import { MessageChannelUtils } from '@ohos/flutter_ohos'; + +export default function MessageChannelUtilsTest() { + describe('MessageChannelUtilsTest', () => { + it('resizeChannelBuffer', 0, () => { + expect(MessageChannelUtils.toString()).not().assertNull(); + }); + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/PathUtils.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/PathUtils.test.ets new file mode 100644 index 0000000000..8f42832818 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/PathUtils.test.ets @@ -0,0 +1,32 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import { PathUtils } from '@ohos/flutter_ohos'; + +export default function PathUtilsTest() { + describe('PathUtilsTest', () => { + it('getFilesDir', 0, () => { + expect(PathUtils.getFilesDir(getContext())).not().assertNull(); + }); + it('getCacheDirectory', 0, () => { + expect(PathUtils.getCacheDirectory(getContext())).not().assertNull(); + }); + it('getDataDirectory', 0, () => { + const name = "flutter"; + expect(PathUtils.getDataDirectory(getContext())).assertContain(name); + }); + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/StringUtils.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/StringUtils.test.ets new file mode 100644 index 0000000000..693d0b188e --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/StringUtils.test.ets @@ -0,0 +1,30 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import { StringUtils } from '@ohos/flutter_ohos'; + +const TAG: string = "stringUtilsTest"; + +export default function StringUtilsTest() { + describe('StringUtilsTest', () => { + it('isNotEmpty', 0, () => { + expect(StringUtils.isNotEmpty(TAG)).assertTrue(); + }); + it('isEmpty', 0, () => { + expect(StringUtils.isEmpty("")).assertTrue(); + }); + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/ToolUtils.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/ToolUtils.test.ets new file mode 100644 index 0000000000..158170ba95 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/ToolUtils.test.ets @@ -0,0 +1,26 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import { ToolUtils } from '@ohos/flutter_ohos'; + +export default function ToolUtilsTest() { + describe('ToolUtilsTest', () => { + it('isObj', 0, () => { + const json = JSON.stringify('object'); + expect(ToolUtils.isObj(json)).assertFalse(); + }); + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/TraceSection.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/TraceSection.test.ets new file mode 100644 index 0000000000..b09b01f109 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/util/TraceSection.test.ets @@ -0,0 +1,34 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import { TraceSection } from '@ohos/flutter_ohos'; + +export default function TraceSectionTest() { + describe('TraceSectionTest', () => { + it('begin', 0, () => { + const sectionName = "DartExecutor"; + expect(TraceSection.begin(sectionName)).assertLarger(0); + }); + it('end', 0, () => { + const sectionName = "DartExecutor"; + TraceSection.end(sectionName); + }); + it('endWithId', 0, () => { + const sectionName = "DartExecutor"; + TraceSection.endWithId(sectionName, 1); + }); + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/view/DynamicView/dynamicViewJson.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/view/DynamicView/dynamicViewJson.test.ets new file mode 100644 index 0000000000..610a7f88c6 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/view/DynamicView/dynamicViewJson.test.ets @@ -0,0 +1,30 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import { createDVModelFromJson } from '@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicViewJson'; + +const TAG: string = "dynamicViewJsonTest"; + +export default function dynamicViewJsonTest() { + describe('dynamicViewJsonTest', () => { + it('createDVModelFromJson', 0, () => { + let dvModel = createDVModelFromJson(JSON.stringify(TAG)); + expect(dvModel) + .not() + .assertNull(); + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/view/FlutterRunArguments.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/view/FlutterRunArguments.test.ets new file mode 100644 index 0000000000..a9d1a07872 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/view/FlutterRunArguments.test.ets @@ -0,0 +1,28 @@ +/* + * 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 { describe, it, expect } from '@ohos/hypium' +import { FlutterRunArguments } from '@ohos/flutter_ohos'; + +const TAG: string = "FlutterRunArgumentsTest"; + +export default function FlutterRunArgumentsTest() { + describe('FlutterRunArgumentsTest', () => { + it('flutterRunArguments', 0, () => { + const flutterRunArguments = new FlutterRunArguments(TAG, TAG, TAG) + expect(flutterRunArguments.bundlePath).assertEqual(TAG) + }) + }) +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/module.json5 b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/module.json5 new file mode 100644 index 0000000000..b4bf32fd9e --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/module.json5 @@ -0,0 +1,28 @@ +/* + * 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": "application_test", + "type": "feature", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/shell/platform/ohos/flutter_embedding/application/src/test/List.test.ets b/shell/platform/ohos/flutter_embedding/application/src/test/List.test.ets new file mode 100644 index 0000000000..312f48fb74 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/test/List.test.ets @@ -0,0 +1,19 @@ +/* + * 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 localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/application/src/test/LocalUnit.test.ets b/shell/platform/ohos/flutter_embedding/application/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000..8ca1b6da13 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/application/src/test/LocalUnit.test.ets @@ -0,0 +1,47 @@ +/* + * 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 { 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/shell/platform/ohos/flutter_embedding/build-profile.json5 b/shell/platform/ohos/flutter_embedding/build-profile.json5 index 4cebb96991..87805d1f43 100755 --- a/shell/platform/ohos/flutter_embedding/build-profile.json5 +++ b/shell/platform/ohos/flutter_embedding/build-profile.json5 @@ -41,6 +41,18 @@ { "name": "flutter", "srcPath": "./flutter" + }, + { + "name": "application", + "srcPath": "./application", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] } ] -} +} \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index 9be47241dc..7216db2888 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -117,7 +117,7 @@ export default class FlutterNapi { Log.e(TAG, "runBundleAndSnapshotFromLibrary this.nativeShellHolderId:" + this.nativeShellHolderId) return; } - flutter.nativeRunBundleAndSnapshotFromLibrary(this.nativeShellHolderId!, bundlePath, entrypointFunctionName, pathToEntrypointFunction, assetManager, entrypointArgs); + flutter.nativeRunBundleAndSnapshotFromLibrary(this.nativeShellHolderId!, bundlePath, entrypointFunctionName as string, pathToEntrypointFunction as string, assetManager, entrypointArgs); }; /** diff --git a/shell/platform/ohos/flutter_embedding/oh-package.json5 b/shell/platform/ohos/flutter_embedding/oh-package.json5 index 6990a41a16..dd166cc567 100755 --- a/shell/platform/ohos/flutter_embedding/oh-package.json5 +++ b/shell/platform/ohos/flutter_embedding/oh-package.json5 @@ -24,6 +24,6 @@ "dependencies": { }, "devDependencies": { - "@ohos/hypium": "1.0.6" + "@ohos/hypium": "1.0.18" } } -- Gitee From 30023841f861d8f54069af7f3848792adb7cc52d Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 4 Nov 2024 15:57:15 +0800 Subject: [PATCH 093/151] =?UTF-8?q?fix:=E8=BF=87=E6=BB=A4=E9=9D=9E?= =?UTF-8?q?=E5=B1=8F=E5=B9=95=E6=98=BE=E7=A4=BA=E7=9A=84=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E4=BB=A5=E6=8F=90=E5=8D=87=E6=80=A7=E8=83=BD?= =?UTF-8?q?,=E8=A7=A3=E5=86=B3=E6=BB=91=E5=8A=A8=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E4=B8=AD=E7=BB=BF=E6=A1=86=E5=9D=90=E6=A0=87=E6=BA=A2=E5=87=BA?= =?UTF-8?q?=E5=B1=8F=E5=B9=95bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 760 +++++++++--------- .../accessibility/ohos_accessibility_bridge.h | 4 +- 2 files changed, 378 insertions(+), 386 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 00fc3acd23..1bba43248d 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -50,7 +50,7 @@ void OhosAccessibilityBridge::OnOhosAccessibilityStateChange( bool ohosAccessibilityEnabled) { native_shell_holder_id_ = shellHolderId; - auto nativeAccessibilityChannel_ = std::make_shared(); + nativeAccessibilityChannel_ = std::make_shared(); if (ohosAccessibilityEnabled) { FML_DLOG(INFO) << "OnOhosAccessibilityEnabled()"; @@ -66,78 +66,6 @@ void OhosAccessibilityBridge::SetNativeShellHolderId(int64_t id) this->native_shell_holder_id_ = id; } -/** - * 当页面状态更新事件,在页面转换、切换、调整大小时发送页面状态更新事件 - */ -void OhosAccessibilityBridge::PageStateUpdate(int64_t elementId) -{ - ArkUI_AccessibilityEventInfo* pageUpdateEventInfo = - OH_ArkUI_CreateAccessibilityEventInfo(); - - ArkUI_AccessibilityElementInfo* _elementInfo = - OH_ArkUI_CreateAccessibilityElementInfo(); - - OH_ArkUI_AccessibilityEventSetEventType( - pageUpdateEventInfo, - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED); - FlutterNodeToElementInfoById(_elementInfo, elementId); - OH_ArkUI_AccessibilityEventSetElementInfo(pageUpdateEventInfo, _elementInfo); - - auto callback = [](int32_t errorCode) { - FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; - }; - - if (provider_ == nullptr) { - FML_DLOG(ERROR) << "PageStateUpdate ->" - "AccessibilityProvider = nullptr"; - return; - } - OH_ArkUI_SendAccessibilityAsyncEvent(provider_, pageUpdateEventInfo, - callback); - - OH_ArkUI_DestoryAccessibilityEventInfo(pageUpdateEventInfo); - OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); - - FML_DLOG(INFO) << "PageStateUpdate is end"; -} - -/** - * 特定节点的焦点请求 (当页面更新时自动请求id=0节点获焦) - */ -void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() -{ - ArkUI_AccessibilityEventInfo* reqFocusEventInfo = - OH_ArkUI_CreateAccessibilityEventInfo(); - ArkUI_AccessibilityElementInfo* elementInfo = - OH_ArkUI_CreateAccessibilityElementInfo(); - - OH_ArkUI_AccessibilityEventSetEventType( - reqFocusEventInfo, - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_REQUEST_ACCESSIBILITY_FOCUS); - - int32_t requestFocusId = 0; - OH_ArkUI_AccessibilityEventSetRequestFocusId(reqFocusEventInfo, - requestFocusId); - - OH_ArkUI_AccessibilityEventSetElementInfo(reqFocusEventInfo, elementInfo); - - auto callback = [](int32_t errorCode) { - FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; - }; - - if (provider_ == nullptr) { - FML_DLOG(ERROR) << "PageStateUpdate ->" - "AccessibilityProvider = nullptr"; - return; - } - OH_ArkUI_SendAccessibilityAsyncEvent(provider_, reqFocusEventInfo, callback); - - OH_ArkUI_DestoryAccessibilityEventInfo(reqFocusEventInfo); - OH_ArkUI_DestoryAccessibilityElementInfo(elementInfo); -} - /** * 从dart侧传递到c++侧的flutter无障碍语义树节点更新过程 */ @@ -161,7 +89,7 @@ void OhosAccessibilityBridge::updateSemantics( // set struct SemanticsNodeExtent auto nodeEx = SetAndGetSemanticsNodeExtent(node); - // print semantics node and flags info for debugging + //print semantics node and flags info for debugging GetSemanticsNodeDebugInfo(node); GetSemanticsFlagsDebugInfo(node); @@ -276,7 +204,7 @@ void OhosAccessibilityBridge::FlutterScrollExecution( int visibleChildren = 0; // handle hidden children at the beginning and end of the list. for (const auto& childId : node.childrenInHitTestOrder) { - auto childNode = getOrCreateFlutterSemanticsNode(childId); + auto childNode = GetFlutterSemanticsNode(childId); if (!childNode.HasFlag(FLAGS_::kIsHidden)) { visibleChildren += 1; } @@ -300,76 +228,75 @@ void OhosAccessibilityBridge::FlutterScrollExecution( } /** - * extent common struct SemanticsNode to - * derived struct SemanticsNodeExtent + * 当页面状态更新事件,在页面转换、切换、调整大小时发送页面状态更新事件 */ -SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent( - flutter::SemanticsNode node) +void OhosAccessibilityBridge::PageStateUpdate(int64_t elementId) { - SemanticsNodeExtent nodeEx = SemanticsNodeExtent(); - nodeEx.id = std::move(node.id); - nodeEx.flags = std::move(node.flags); - nodeEx.actions = std::move(node.actions); - nodeEx.maxValueLength = std::move(node.maxValueLength); - nodeEx.currentValueLength = std::move(node.currentValueLength); - nodeEx.textSelectionBase = std::move(node.textSelectionBase); - nodeEx.textSelectionExtent = std::move(node.textSelectionExtent); - nodeEx.platformViewId = std::move(node.platformViewId); - nodeEx.scrollChildren = std::move(node.scrollChildren); - nodeEx.scrollIndex = std::move(node.scrollIndex); - nodeEx.scrollPosition = std::move(node.scrollPosition); - nodeEx.scrollExtentMax = std::move(node.scrollExtentMax); - nodeEx.scrollExtentMin = std::move(node.scrollExtentMin); - nodeEx.elevation = std::move(node.elevation); - nodeEx.thickness = std::move(node.thickness); - nodeEx.label = std::move(node.label); - nodeEx.labelAttributes = std::move(node.labelAttributes); - nodeEx.hint = std::move(node.hint); - nodeEx.hintAttributes = std::move(node.hintAttributes); - nodeEx.value = std::move(node.value); - nodeEx.valueAttributes = std::move(node.valueAttributes); - nodeEx.increasedValue = std::move(node.increasedValue); - nodeEx.increasedValueAttributes = std::move(node.increasedValueAttributes); - nodeEx.decreasedValue = std::move(node.decreasedValue); - nodeEx.decreasedValueAttributes = std::move(node.decreasedValueAttributes); - nodeEx.tooltip = std::move(node.tooltip); - nodeEx.textDirection = std::move(node.textDirection); + ArkUI_AccessibilityEventInfo* pageUpdateEventInfo = + OH_ArkUI_CreateAccessibilityEventInfo(); - nodeEx.rect = std::move(node.rect); - nodeEx.transform = std::move(node.transform); - nodeEx.childrenInTraversalOrder = std::move(node.childrenInTraversalOrder); - nodeEx.childrenInHitTestOrder = std::move(node.childrenInHitTestOrder); - nodeEx.customAccessibilityActions = - std::move(node.customAccessibilityActions); - return nodeEx; -} + ArkUI_AccessibilityElementInfo* _elementInfo = + OH_ArkUI_CreateAccessibilityElementInfo(); -/** - * 判断当前节点是否已经滑动 - */ -bool OhosAccessibilityBridge::HasScrolled( - const flutter::SemanticsNode& flutterNode) -{ - return flutterNode.scrollPosition != std::nan(""); -} -/** - * 判断是否可滑动 - */ -bool OhosAccessibilityBridge::IsNodeScrollable( - flutter::SemanticsNode flutterNode) -{ - return flutterNode.HasAction(ACTIONS_::kScrollLeft) || - flutterNode.HasAction(ACTIONS_::kScrollRight) || - flutterNode.HasAction(ACTIONS_::kScrollUp) || - flutterNode.HasAction(ACTIONS_::kScrollDown); + OH_ArkUI_AccessibilityEventSetEventType( + pageUpdateEventInfo, + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED); + FlutterNodeToElementInfoById(_elementInfo, elementId); + OH_ArkUI_AccessibilityEventSetElementInfo(pageUpdateEventInfo, _elementInfo); + + auto callback = [](int32_t errorCode) { + FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; + }; + + if (provider_ == nullptr) { + FML_DLOG(ERROR) << "PageStateUpdate ->" + "AccessibilityProvider = nullptr"; + return; + } + OH_ArkUI_SendAccessibilityAsyncEvent(provider_, pageUpdateEventInfo, + callback); + + OH_ArkUI_DestoryAccessibilityEventInfo(pageUpdateEventInfo); + OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); + + FML_DLOG(INFO) << "PageStateUpdate is end"; } + /** - * 判断当前节点组件是否是滑动组件,如: listview, gridview等 + * 特定节点的焦点请求 (当页面更新时自动请求id=0节点获焦) */ -bool OhosAccessibilityBridge::IsScrollableWidget( - flutter::SemanticsNode flutterNode) +void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() { - return flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); + ArkUI_AccessibilityEventInfo* reqFocusEventInfo = + OH_ArkUI_CreateAccessibilityEventInfo(); + ArkUI_AccessibilityElementInfo* elementInfo = + OH_ArkUI_CreateAccessibilityElementInfo(); + + OH_ArkUI_AccessibilityEventSetEventType( + reqFocusEventInfo, + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_REQUEST_ACCESSIBILITY_FOCUS); + + int32_t requestFocusId = 0; + OH_ArkUI_AccessibilityEventSetRequestFocusId(reqFocusEventInfo, + requestFocusId); + + OH_ArkUI_AccessibilityEventSetElementInfo(reqFocusEventInfo, elementInfo); + + auto callback = [](int32_t errorCode) { + FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; + }; + + if (provider_ == nullptr) { + FML_DLOG(ERROR) << "PageStateUpdate ->" + "AccessibilityProvider = nullptr"; + return; + } + OH_ArkUI_SendAccessibilityAsyncEvent(provider_, reqFocusEventInfo, callback); + + OH_ArkUI_DestoryAccessibilityEventInfo(reqFocusEventInfo); + OH_ArkUI_DestoryAccessibilityElementInfo(elementInfo); } /** @@ -416,19 +343,35 @@ void OhosAccessibilityBridge::Announce(std::unique_ptr& message) return; } +//获取根节点 +flutter::SemanticsNode OhosAccessibilityBridge::GetFlutterRootSemanticsNode() +{ + if (!flutterSemanticsTree_.size()) { + FML_DLOG(ERROR) + << "GetFlutterRootSemanticsNode -> flutterSemanticsTree_.size()=0"; + return flutter::SemanticsNode{}; + } + if (flutterSemanticsTree_.find(0) == flutterSemanticsTree_.end()) { + FML_DLOG(ERROR) << "GetFlutterRootSemanticsNode -> flutterSemanticsTree_ " + "has no keys = 0"; + return flutter::SemanticsNode{}; + } + return flutterSemanticsTree_.at(0); +} + /** * 根据nodeid获取或创建flutter语义节点 */ -flutter::SemanticsNode OhosAccessibilityBridge::getOrCreateFlutterSemanticsNode( +flutter::SemanticsNode OhosAccessibilityBridge::GetFlutterSemanticsNode( int32_t id) { flutter::SemanticsNode node; if (flutterSemanticsTree_.count(id) > 0) { return flutterSemanticsTree_.at(id); - FML_DLOG(INFO) << "getOrCreateFlutterSemanticsNode get node.id=" << id; + FML_DLOG(INFO) << "GetFlutterSemanticsNode get node.id=" << id; } else { FML_DLOG(ERROR) - << "getOrCreateFlutterSemanticsNode flutterSemanticsTree_ = null" << id; + << "GetFlutterSemanticsNode flutterSemanticsTree_ = null" << id; return flutter::SemanticsNode{}; } } @@ -592,7 +535,7 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( // 获取当前flutter节点的父节点的相对rect int32_t parentId = GetParentId(currNode.id); - auto parentNode = getOrCreateFlutterSemanticsNode(parentId); + auto parentNode = GetFlutterSemanticsNode(parentId); auto parentRight = parentNode.rect.fRight; auto parentBottom = parentNode.rect.fBottom; @@ -603,10 +546,10 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( auto realParentRight = _rectPairs.second.first; auto realParentBottom = _rectPairs.second.second; - // 获取root节点的绝对坐标 + // 获取root节点的绝对坐标, 即xcomponent屏幕长宽 auto _rootRect = GetAbsoluteScreenRect(0); - // auto rootRight = _rootRect.second.first; - auto rootBottom = _rootRect.second.second; + // float rootWidth = _rootRect.second.first; + auto rootHeight = _rootRect.second.second; // 真实缩放系数 float realScaleFactor = realParentRight / parentRight * 1.0; @@ -636,7 +579,6 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( newBottom = (currTop + _kMTransY + currBottom) * realScaleFactor + realParentTop; } - // 若子节点rect超过父节点则跳过显示(单个屏幕显示不下,滑动再重新显示) if (newLeft < realParentLeft || newTop < realParentTop || newRight > realParentRight || newBottom > realParentBottom || @@ -645,9 +587,11 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( "bigger than parentRect -> { nodeId: " << currNode.id << ", (" << newLeft << ", " << newTop << ", " << newRight << ", " << newBottom << ")}"; - // 防止溢出屏幕坐标 - newTop = realParentTop - rootBottom; - newBottom = realParentBottom - rootBottom; + // 防止滑动场景下绿框坐标超出屏幕范围,进行正则化处理 + // newLeft = static_cast(newLeft) % static_cast(rootWidth); + newTop = static_cast(newTop) % static_cast(rootHeight); + // newRight = static_cast(newRight) % static_cast(rootWidth); + newBottom = static_cast(newBottom) % static_cast(rootHeight); SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); } else { @@ -676,7 +620,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( if (elementId == 0 || elementId == -1) { // 获取flutter的root节点 flutter::SemanticsNode flutterNode = - getOrCreateFlutterSemanticsNode(static_cast(0)); + GetFlutterSemanticsNode(static_cast(0)); // 设置elementinfo的屏幕坐标范围 int32_t left = static_cast(flutterNode.rect.fLeft); @@ -864,7 +808,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( int64_t elementId) { flutter::SemanticsNode flutterNode = - getOrCreateFlutterSemanticsNode(static_cast(elementId)); + GetFlutterSemanticsNode(static_cast(elementId)); // set elementinfo id OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, @@ -1046,108 +990,14 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( } /** - * 判断当前节点是否为textfield文本框 - */ -bool OhosAccessibilityBridge::IsTextField(flutter::SemanticsNode flutterNode) -{ - return flutterNode.HasFlag(FLAGS_::kIsTextField); -} -/** - * 判断当前节点是否为滑动条slider类型 - */ -bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) -{ - return flutterNode.HasFlag(FLAGS_::kIsSlider); -} -/** - * 判断当前flutter节点组件是否可点击 - */ -bool OhosAccessibilityBridge::IsNodeClickable( - flutter::SemanticsNode flutterNode) -{ - return flutterNode.HasAction(ACTIONS_::kTap) || - flutterNode.HasFlag(FLAGS_::kHasCheckedState) || - flutterNode.HasFlag(FLAGS_::kIsButton) || - flutterNode.HasFlag(FLAGS_::kIsTextField) || - flutterNode.HasFlag(FLAGS_::kIsImage) || - flutterNode.HasFlag(FLAGS_::kIsLiveRegion) || - flutterNode.HasFlag(FLAGS_::kIsMultiline) || - flutterNode.HasFlag(FLAGS_::kIsLink) || - flutterNode.HasFlag(FLAGS_::kIsSlider) || - flutterNode.HasFlag(FLAGS_::kIsKeyboardKey) || - flutterNode.HasFlag(FLAGS_::kHasToggledState) || - flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); -} -/** - * 判断当前flutter节点组件是否可显示 + * Called to obtain element information based on a specified node. + * NOTE:该arkui接口需要在系统无障碍服务开启时,才能触发调用 */ -bool OhosAccessibilityBridge::IsNodeVisible( - flutter::SemanticsNode flutterNode) -{ - return flutterNode.HasFlag(FLAGS_::kIsHidden) ? false : true; -} -/** - * 判断当前flutter节点组件是否具备checkable属性 - */ -bool OhosAccessibilityBridge::IsNodeCheckable( - flutter::SemanticsNode flutterNode) -{ - return flutterNode.HasFlag(FLAGS_::kHasCheckedState) || - flutterNode.HasFlag(FLAGS_::kHasToggledState); -} -/** - * 判断当前flutter节点组件是否checked/unchecked(checkbox、radio button) - */ -bool OhosAccessibilityBridge::IsNodeChecked( - flutter::SemanticsNode flutterNode) -{ - return flutterNode.HasFlag(FLAGS_::kIsChecked) || - flutterNode.HasFlag(FLAGS_::kIsToggled); -} -/** - * 判断当前flutter节点组件是否选中 - */ -bool OhosAccessibilityBridge::IsNodeSelected( - flutter::SemanticsNode flutterNode) -{ - return flutterNode.HasFlag(FLAGS_::kIsSelected); -} -/** - * 判断当前flutter节点组件是否为密码输入框 - */ -bool OhosAccessibilityBridge::IsNodePassword( - flutter::SemanticsNode flutterNode) -{ - return flutterNode.HasFlag(FLAGS_::kIsTextField) && - flutterNode.HasFlag(FLAGS_::kIsObscured); -} -/** - * 判断当前flutter节点组件是否支持长按功能 - */ -bool OhosAccessibilityBridge::IsNodeHasLongPress( - flutter::SemanticsNode flutterNode) -{ - return flutterNode.HasAction(ACTIONS_::kLongPress); -} -/** - * 判断当前flutter节点是否enabled - */ -bool OhosAccessibilityBridge::IsNodeEnabled( - flutter::SemanticsNode flutterNode) -{ - return !flutterNode.HasFlag(FLAGS_::kHasEnabledState) || - flutterNode.HasFlag(FLAGS_::kIsEnabled); -} - -/** - * Called to obtain element information based on a specified node. - * NOTE:该arkui接口需要在系统无障碍服务开启时,才能触发调用 - */ -int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( - int64_t elementId, - ArkUI_AccessibilitySearchMode mode, - int32_t requestId, - ArkUI_AccessibilityElementInfoList* elementList) +int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( + int64_t elementId, + ArkUI_AccessibilitySearchMode mode, + int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList) { FML_DLOG(INFO) << "#### FindAccessibilityNodeInfosById input-params ####: elementId = " @@ -1173,8 +1023,10 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } - auto flutterNode = getOrCreateFlutterSemanticsNode(static_cast(elementId)); - if(!IsNodeVisible(flutterNode)) { + auto flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); + bool VISIBLE_STATE = elementId == -1; + if (!VISIBLE_STATE && !IsNodeVisible(flutterNode)) { + FML_DLOG(INFO) << "filter hidden nodes, elementId:" << elementId; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } @@ -1185,14 +1037,13 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( int64_t elementInfoCount = static_cast(flutterSemanticsTree_.size()); for (int64_t i = 1; i < elementInfoCount; i++) { - auto childNode = getOrCreateFlutterSemanticsNode(static_cast(i)); + auto childNode = GetFlutterSemanticsNode(static_cast(i)); if (IsNodeVisible(childNode)) { ArkUI_AccessibilityElementInfo* newElementInfo = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); FlutterNodeToElementInfoById(newElementInfo, i); } } - } else if (mode == ArkUI_AccessibilitySearchMode:: ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS) { @@ -1214,7 +1065,6 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( if (IsNodeVisible(flutterNode)) { FlutterNodeToElementInfoById(elementInfoFromList, elementId); } - } else if ( mode == ArkUI_AccessibilitySearchMode:: @@ -1224,126 +1074,22 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( int64_t elementInfoCount = static_cast(flutterSemanticsTree_.size()); for (int64_t i = 1; i < elementInfoCount; i++) { - auto childNode = getOrCreateFlutterSemanticsNode(static_cast(i)); + auto childNode = GetFlutterSemanticsNode(static_cast(i)); if (IsNodeVisible(childNode)) { ArkUI_AccessibilityElementInfo* newElementInfo = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); FlutterNodeToElementInfoById(newElementInfo, i); } } - } else { if (IsNodeVisible(flutterNode)) { FlutterNodeToElementInfoById(elementInfoFromList, elementId); } } - FML_DLOG(INFO) << "--- FindAccessibilityNodeInfosById is end ---"; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; } -/** - * Called to obtain element information based on a specified node and text - * content. - */ -int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosByText( - int64_t elementId, - const char* text, - int32_t requestId, - ArkUI_AccessibilityElementInfoList* elementList) -{ - FML_DLOG(INFO) << "=== FindAccessibilityNodeInfosByText is end ==="; - return 0; -} -int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( - int64_t elementId, - ArkUI_AccessibilityFocusType focusType, - int32_t requestId, - ArkUI_AccessibilityElementInfo* elementinfo) -{ - FML_DLOG(INFO) << "=== FindFocusedAccessibilityNode is end ==="; - - return 0; -} -int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( - int64_t elementId, - ArkUI_AccessibilityFocusMoveDirection direction, - int32_t requestId, - ArkUI_AccessibilityElementInfo* elementList) { - FML_DLOG(INFO) << "=== FindNextFocusAccessibilityNode is end ==="; - return 0; -} - -int32_t OhosAccessibilityBridge::ClearFocusedFocusAccessibilityNode() -{ - FML_DLOG(INFO) << "=== ClearFocusedFocusAccessibilityNode is end ==="; - return 0; -} -int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( - int64_t elementId, - int32_t requestId, - int32_t* index) -{ - FML_DLOG(INFO) << "=== GetAccessibilityNodeCursorPosition is end ==="; - return 0; -} - -/** - * 将arkui的action类型转化为flutter的action类型 - */ -flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( - ArkUI_Accessibility_ActionType arkui_action) -{ - switch (arkui_action) { - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: - return ACTIONS_::kTap; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: - return ACTIONS_::kLongPress; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: - return ACTIONS_::kScrollUp; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: - return ACTIONS_::kScrollDown; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: - return ACTIONS_::kCopy; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: - return ACTIONS_::kCut; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: - return ACTIONS_::kDidGainAccessibilityFocus; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: - return ACTIONS_::kDidLoseAccessibilityFocus; - - // Text selection action, requiring the setting of selectTextBegin, - // TextEnd, and TextInForward parameters to select a text - // segment in the text box. */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: - return ACTIONS_::kSetSelection; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: - return ACTIONS_::kSetText; - - default: - // might not match to the valid action in arkui - return ACTIONS_::kCustomAction; - } -} - /** * 解析flutter语义动作,并通过NativAccessibilityChannel分发 */ @@ -1352,7 +1098,7 @@ void OhosAccessibilityBridge::DispatchSemanticsAction( flutter::SemanticsAction action, fml::MallocMapping args) { - auto nativeAccessibilityChannel_ = std::make_shared(); + nativeAccessibilityChannel_ = std::make_shared(); nativeAccessibilityChannel_->DispatchSemanticsAction(native_shell_holder_id_, id, action, @@ -1381,7 +1127,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( // 获取当前elementid对应的flutter语义节点 auto flutterNode = - getOrCreateFlutterSemanticsNode(static_cast(elementId)); + GetFlutterSemanticsNode(static_cast(elementId)); // 根据当前elementid和无障碍动作类型,发送无障碍事件 switch (action) { @@ -1427,7 +1173,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( auto flutterGainFocusAction = ArkuiActionsToFlutterActions(action); DispatchSemanticsAction(static_cast(elementId), flutterGainFocusAction, {}); - /** Accessibility focus event, sent after the UI component responds. 32768 */ auto focusEventType = ArkUI_AccessibilityEventType:: @@ -1435,14 +1180,12 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( Flutter_SendAccessibilityAsyncEvent(elementId, focusEventType); FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: focus(" << action << ")" << " event: focus(" << focusEventType << ")"; - if (flutterNode.HasAction(ACTIONS_::kIncrease) || flutterNode.HasAction(ACTIONS_::kDecrease)) { Flutter_SendAccessibilityAsyncEvent( elementId, ArkUI_AccessibilityEventType:: ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); } - break; } @@ -1513,11 +1256,9 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( auto flutterScrollDownAction = ArkuiActionsToFlutterActions(action); DispatchSemanticsAction(static_cast(elementId), flutterScrollDownAction, {}); - } else if (flutterNode.HasAction(ACTIONS_::kScrollRight)) { DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kScrollRight, {}); - } else if (flutterNode.HasAction(ACTIONS_::kDecrease)) { flutterNode.value = flutterNode.decreasedValue; flutterNode.valueAttributes = flutterNode.decreasedValueAttributes; @@ -1527,7 +1268,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kDecrease, {}); - } else { } std::string currComponetType = GetNodeComponentType(flutterNode); @@ -1630,6 +1370,108 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; } +/** + * Called to obtain element information based on a specified node and text + * content. + */ +int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosByText( + int64_t elementId, + const char* text, + int32_t requestId, + ArkUI_AccessibilityElementInfoList* elementList) +{ + FML_DLOG(INFO) << "=== FindAccessibilityNodeInfosByText is end ==="; + return 0; +} +int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( + int64_t elementId, + ArkUI_AccessibilityFocusType focusType, + int32_t requestId, + ArkUI_AccessibilityElementInfo* elementinfo) +{ + FML_DLOG(INFO) << "=== FindFocusedAccessibilityNode is end ==="; + + return 0; +} +int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( + int64_t elementId, + ArkUI_AccessibilityFocusMoveDirection direction, + int32_t requestId, + ArkUI_AccessibilityElementInfo* elementList) { + FML_DLOG(INFO) << "=== FindNextFocusAccessibilityNode is end ==="; + return 0; +} + +int32_t OhosAccessibilityBridge::ClearFocusedFocusAccessibilityNode() +{ + FML_DLOG(INFO) << "=== ClearFocusedFocusAccessibilityNode is end ==="; + return 0; +} +int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( + int64_t elementId, + int32_t requestId, + int32_t* index) +{ + FML_DLOG(INFO) << "=== GetAccessibilityNodeCursorPosition is end ==="; + return 0; +} + +/** + * 将arkui的action类型转化为flutter的action类型 + */ +flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( + ArkUI_Accessibility_ActionType arkui_action) +{ + switch (arkui_action) { + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: + return ACTIONS_::kTap; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: + return ACTIONS_::kLongPress; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: + return ACTIONS_::kScrollUp; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: + return ACTIONS_::kScrollDown; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: + return ACTIONS_::kCopy; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: + return ACTIONS_::kCut; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: + return ACTIONS_::kDidGainAccessibilityFocus; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: + return ACTIONS_::kDidLoseAccessibilityFocus; + + // Text selection action, requiring the setting of selectTextBegin, + // TextEnd, and TextInForward parameters to select a text + // segment in the text box. */ + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: + return ACTIONS_::kSetSelection; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: + return ACTIONS_::kSetText; + + default: + // might not match to the valid action in arkui + return ACTIONS_::kCustomAction; + } +} + /** * 自定义无障碍异步事件发送 */ @@ -1786,20 +1628,125 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( return "Widget" + std::to_string(node.id); } -// 获取根节点 -flutter::SemanticsNode OhosAccessibilityBridge::getFlutterRootSemanticsNode() +/** + * 判断当前节点是否为textfield文本框 + */ +bool OhosAccessibilityBridge::IsTextField(flutter::SemanticsNode flutterNode) { - if (!flutterSemanticsTree_.size()) { - FML_DLOG(ERROR) - << "getFlutterRootSemanticsNode -> flutterSemanticsTree_.size()=0"; - return flutter::SemanticsNode{}; - } - if (flutterSemanticsTree_.find(0) == flutterSemanticsTree_.end()) { - FML_DLOG(ERROR) << "getFlutterRootSemanticsNode -> flutterSemanticsTree_ " - "has no keys = 0"; - return flutter::SemanticsNode{}; - } - return flutterSemanticsTree_.at(0); + return flutterNode.HasFlag(FLAGS_::kIsTextField); +} +/** + * 判断当前节点是否为滑动条slider类型 + */ +bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) +{ + return flutterNode.HasFlag(FLAGS_::kIsSlider); +} +/** + * 判断当前flutter节点组件是否可点击 + */ +bool OhosAccessibilityBridge::IsNodeClickable( + flutter::SemanticsNode flutterNode) +{ + return flutterNode.HasAction(ACTIONS_::kTap) || + flutterNode.HasFlag(FLAGS_::kHasCheckedState) || + flutterNode.HasFlag(FLAGS_::kIsButton) || + flutterNode.HasFlag(FLAGS_::kIsTextField) || + flutterNode.HasFlag(FLAGS_::kIsImage) || + flutterNode.HasFlag(FLAGS_::kIsLiveRegion) || + flutterNode.HasFlag(FLAGS_::kIsMultiline) || + flutterNode.HasFlag(FLAGS_::kIsLink) || + flutterNode.HasFlag(FLAGS_::kIsSlider) || + flutterNode.HasFlag(FLAGS_::kIsKeyboardKey) || + flutterNode.HasFlag(FLAGS_::kHasToggledState) || + flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); +} +/** + * 判断当前flutter节点组件是否可显示 + */ +bool OhosAccessibilityBridge::IsNodeVisible( + flutter::SemanticsNode flutterNode) +{ + return flutterNode.HasFlag(FLAGS_::kIsHidden) ? false : true; +} +/** + * 判断当前flutter节点组件是否具备checkable属性 + */ +bool OhosAccessibilityBridge::IsNodeCheckable( + flutter::SemanticsNode flutterNode) +{ + return flutterNode.HasFlag(FLAGS_::kHasCheckedState) || + flutterNode.HasFlag(FLAGS_::kHasToggledState); +} +/** + * 判断当前flutter节点组件是否checked/unchecked(checkbox、radio button) + */ +bool OhosAccessibilityBridge::IsNodeChecked( + flutter::SemanticsNode flutterNode) +{ + return flutterNode.HasFlag(FLAGS_::kIsChecked) || + flutterNode.HasFlag(FLAGS_::kIsToggled); +} +/** + * 判断当前flutter节点组件是否选中 + */ +bool OhosAccessibilityBridge::IsNodeSelected( + flutter::SemanticsNode flutterNode) +{ + return flutterNode.HasFlag(FLAGS_::kIsSelected); +} +/** + * 判断当前flutter节点组件是否为密码输入框 + */ +bool OhosAccessibilityBridge::IsNodePassword( + flutter::SemanticsNode flutterNode) +{ + return flutterNode.HasFlag(FLAGS_::kIsTextField) && + flutterNode.HasFlag(FLAGS_::kIsObscured); +} +/** + * 判断当前flutter节点组件是否支持长按功能 + */ +bool OhosAccessibilityBridge::IsNodeHasLongPress( + flutter::SemanticsNode flutterNode) +{ + return flutterNode.HasAction(ACTIONS_::kLongPress); +} +/** + * 判断当前flutter节点是否enabled + */ +bool OhosAccessibilityBridge::IsNodeEnabled( + flutter::SemanticsNode flutterNode) +{ + return !flutterNode.HasFlag(FLAGS_::kHasEnabledState) || + flutterNode.HasFlag(FLAGS_::kIsEnabled); +} +/** + * 判断当前节点是否已经滑动 + */ +bool OhosAccessibilityBridge::HasScrolled( + const flutter::SemanticsNode& flutterNode) +{ + return flutterNode.scrollPosition != std::nan(""); +} +/** + * 判断是否可滑动 + */ +bool OhosAccessibilityBridge::IsNodeScrollable( + flutter::SemanticsNode flutterNode) +{ + return flutterNode.HasAction(ACTIONS_::kScrollLeft) || + flutterNode.HasAction(ACTIONS_::kScrollRight) || + flutterNode.HasAction(ACTIONS_::kScrollUp) || + flutterNode.HasAction(ACTIONS_::kScrollDown); +} +/** + * 判断当前节点组件是否是滑动组件,如: listview, gridview等 + */ +bool OhosAccessibilityBridge::IsScrollableWidget( + flutter::SemanticsNode flutterNode) +{ + return flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); } void OhosAccessibilityBridge::AddRouteNodes( @@ -1810,7 +1757,7 @@ void OhosAccessibilityBridge::AddRouteNodes( edges.emplace_back(node); } for (auto& childNodeId : node.childrenInTraversalOrder) { - auto childNode = getOrCreateFlutterSemanticsNode(childNodeId); + auto childNode = GetFlutterSemanticsNode(childNodeId); AddRouteNodes(edges, childNode); } } @@ -1821,7 +1768,7 @@ std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) return node.label; } for (auto& childNodeId : node.childrenInTraversalOrder) { - auto childNode = getOrCreateFlutterSemanticsNode(childNodeId); + auto childNode = GetFlutterSemanticsNode(childNodeId); std::string newName = GetRouteName(childNode); if (!newName.empty()) { return newName; @@ -1878,6 +1825,51 @@ void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() flutterNavigationVec_.clear(); } +/** + * extent common struct SemanticsNode to + * derived struct SemanticsNodeExtent + */ +SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent( + flutter::SemanticsNode node) +{ + SemanticsNodeExtent nodeEx = SemanticsNodeExtent(); + nodeEx.id = std::move(node.id); + nodeEx.flags = std::move(node.flags); + nodeEx.actions = std::move(node.actions); + nodeEx.maxValueLength = std::move(node.maxValueLength); + nodeEx.currentValueLength = std::move(node.currentValueLength); + nodeEx.textSelectionBase = std::move(node.textSelectionBase); + nodeEx.textSelectionExtent = std::move(node.textSelectionExtent); + nodeEx.platformViewId = std::move(node.platformViewId); + nodeEx.scrollChildren = std::move(node.scrollChildren); + nodeEx.scrollIndex = std::move(node.scrollIndex); + nodeEx.scrollPosition = std::move(node.scrollPosition); + nodeEx.scrollExtentMax = std::move(node.scrollExtentMax); + nodeEx.scrollExtentMin = std::move(node.scrollExtentMin); + nodeEx.elevation = std::move(node.elevation); + nodeEx.thickness = std::move(node.thickness); + nodeEx.label = std::move(node.label); + nodeEx.labelAttributes = std::move(node.labelAttributes); + nodeEx.hint = std::move(node.hint); + nodeEx.hintAttributes = std::move(node.hintAttributes); + nodeEx.value = std::move(node.value); + nodeEx.valueAttributes = std::move(node.valueAttributes); + nodeEx.increasedValue = std::move(node.increasedValue); + nodeEx.increasedValueAttributes = std::move(node.increasedValueAttributes); + nodeEx.decreasedValue = std::move(node.decreasedValue); + nodeEx.decreasedValueAttributes = std::move(node.decreasedValueAttributes); + nodeEx.tooltip = std::move(node.tooltip); + nodeEx.textDirection = std::move(node.textDirection); + + nodeEx.rect = std::move(node.rect); + nodeEx.transform = std::move(node.transform); + nodeEx.childrenInTraversalOrder = std::move(node.childrenInTraversalOrder); + nodeEx.childrenInHitTestOrder = std::move(node.childrenInHitTestOrder); + nodeEx.customAccessibilityActions = + std::move(node.customAccessibilityActions); + return nodeEx; +} + void OhosAccessibilityBridge::GetSemanticsNodeDebugInfo( flutter::SemanticsNode node) { diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index e9e171c53c..6092e0ba2a 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -84,7 +84,7 @@ class OhosAccessibilityBridge { void Announce(std::unique_ptr& message); - flutter::SemanticsNode getOrCreateFlutterSemanticsNode(int32_t id); + flutter::SemanticsNode GetFlutterSemanticsNode(int32_t id); int32_t FindAccessibilityNodeInfosById( int64_t elementId, @@ -229,7 +229,7 @@ class OhosAccessibilityBridge { void FlutterTreeToArkuiTree( ArkUI_AccessibilityElementInfoList* elementInfoList); - flutter::SemanticsNode getFlutterRootSemanticsNode(); + flutter::SemanticsNode GetFlutterRootSemanticsNode(); std::string GetNodeComponentType(const flutter::SemanticsNode& node); flutter::SemanticsAction ArkuiActionsToFlutterActions( ArkUI_Accessibility_ActionType arkui_action); -- Gitee From 2aec3b6a2d7ddcfea284dcbdb80b0e6d3fc4ccf0 Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 4 Nov 2024 21:09:03 +0800 Subject: [PATCH 094/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E6=97=A0?= =?UTF-8?q?=E9=9A=9C=E7=A2=8D=E5=AF=BC=E8=88=AA=E7=89=B9=E5=BE=81=E5=8A=9F?= =?UTF-8?q?=E8=83=BD,=E4=BC=98=E5=8C=96=E9=83=A8=E5=88=86=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 19 +++++----- .../accessibility/ohos_accessibility_bridge.h | 6 ++-- .../ohos_accessibility_features.cpp | 35 +++++++++++++------ .../ohos_accessibility_features.h | 25 ++++++++++--- .../ets/embedding/ohos/FlutterAbility.ets | 2 +- .../ohos/napi/platform_view_ohos_napi.cpp | 5 ++- 6 files changed, 62 insertions(+), 30 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 1bba43248d..f463cf2e69 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -51,12 +51,14 @@ void OhosAccessibilityBridge::OnOhosAccessibilityStateChange( { native_shell_holder_id_ = shellHolderId; nativeAccessibilityChannel_ = std::make_shared(); + accessibilityFeatures_ = std::make_shared(); if (ohosAccessibilityEnabled) { FML_DLOG(INFO) << "OnOhosAccessibilityEnabled()"; nativeAccessibilityChannel_->OnOhosAccessibilityEnabled(native_shell_holder_id_); } else { FML_DLOG(INFO) << "OnOhosAccessibilityEnabled()"; + accessibilityFeatures_->SetAccessibleNavigation(false, native_shell_holder_id_); nativeAccessibilityChannel_->OnOhosAccessibilityDisabled(native_shell_holder_id_); } } @@ -100,11 +102,6 @@ void OhosAccessibilityBridge::updateSemantics( */ flutterSemanticsTree_[node.id] = node; - // 若当前更新节点是隐藏的,则跳过 - if (node.HasFlag(FLAGS_::kIsHidden)) { - continue; - } - // 获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 int32_t childNodeCount = node.childrenInTraversalOrder.size(); for (int32_t i = 0; i < childNodeCount; i++) { @@ -230,7 +227,7 @@ void OhosAccessibilityBridge::FlutterScrollExecution( /** * 当页面状态更新事件,在页面转换、切换、调整大小时发送页面状态更新事件 */ -void OhosAccessibilityBridge::PageStateUpdate(int64_t elementId) +void OhosAccessibilityBridge::PageStateUpdate() { ArkUI_AccessibilityEventInfo* pageUpdateEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); @@ -241,8 +238,8 @@ void OhosAccessibilityBridge::PageStateUpdate(int64_t elementId) OH_ArkUI_AccessibilityEventSetEventType( pageUpdateEventInfo, ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED); - FlutterNodeToElementInfoById(_elementInfo, elementId); + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); + // FlutterNodeToElementInfoById(_elementInfo, elementId); OH_ArkUI_AccessibilityEventSetElementInfo(pageUpdateEventInfo, _elementInfo); auto callback = [](int32_t errorCode) { @@ -1014,6 +1011,10 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } + // 开启无障碍导航功能 + accessibilityFeatures_->SetAccessibleNavigation(true, + native_shell_holder_id_); + // 从elementinfolist中获取elementinfo ArkUI_AccessibilityElementInfo* elementInfoFromList = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); @@ -1023,6 +1024,7 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } + // 过滤非当前屏幕显示的语义节点创建、配置,防止溢出屏幕坐标绘制bug以及优化性能开销 auto flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); bool VISIBLE_STATE = elementId == -1; if (!VISIBLE_STATE && !IsNodeVisible(flutterNode)) { @@ -1098,7 +1100,6 @@ void OhosAccessibilityBridge::DispatchSemanticsAction( flutter::SemanticsAction action, fml::MallocMapping args) { - nativeAccessibilityChannel_ = std::make_shared(); nativeAccessibilityChannel_->DispatchSemanticsAction(native_shell_holder_id_, id, action, diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 6092e0ba2a..7a669b53e4 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -24,6 +24,7 @@ #include "flutter/lib/ui/semantics/custom_accessibility_action.h" #include "flutter/lib/ui/semantics/semantics_node.h" #include "native_accessibility_channel.h" +#include "ohos_accessibility_features.h" namespace flutter { typedef flutter::SemanticsFlags FLAGS_; @@ -138,13 +139,14 @@ class OhosAccessibilityBridge { void FlutterScrollExecution( flutter::SemanticsNode node, ArkUI_AccessibilityElementInfo* elementInfoFromList); - + void ClearFlutterSemanticsCaches(); private: OhosAccessibilityBridge(); static OhosAccessibilityBridge* bridgeInstance; std::shared_ptr nativeAccessibilityChannel_; + std::shared_ptr accessibilityFeatures_; static const int32_t ROOT_NODE_ID = 0; constexpr static const double SCROLL_EXTENT_FOR_INFINITY = 100000.0; @@ -268,7 +270,7 @@ class OhosAccessibilityBridge { void GetCustomActionDebugInfo( flutter::CustomAccessibilityAction customAccessibilityAction); - void PageStateUpdate(int64_t elementId); + void PageStateUpdate(); void RequestFocusWhenPageUpdate(); bool Contains(const std::string source, const std::string target); diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp index 3e0b16b1b7..f82bc0bbb8 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp @@ -18,32 +18,47 @@ namespace flutter { -OhosAccessibilityFeatures OhosAccessibilityFeatures::instance; - OhosAccessibilityFeatures::OhosAccessibilityFeatures() {}; OhosAccessibilityFeatures::~OhosAccessibilityFeatures() {}; -OhosAccessibilityFeatures* OhosAccessibilityFeatures::GetInstance() { - return &OhosAccessibilityFeatures::instance; +/** + * 无障碍特征之无障碍导航 + */ +void OhosAccessibilityFeatures::SetAccessibleNavigation( + bool isAccessibleNavigation, + int64_t shell_holder_id) +{ + if (ACCESSIBLE_NAVIGATION == isAccessibleNavigation) { + return; + } + ACCESSIBLE_NAVIGATION = isAccessibleNavigation; + if (ACCESSIBLE_NAVIGATION) { + accessibilityFeatureFlags |= + static_cast(AccessibilityFeatures::AccessibleNavigation); + FML_DLOG(INFO) << "SetAccessibleNavigation -> accessibilityFeatureFlags: " + << accessibilityFeatureFlags; + } else { + accessibilityFeatureFlags &= + ~static_cast(AccessibilityFeatures::AccessibleNavigation); + } + SendAccessibilityFlags(shell_holder_id); } /** - * bold text for AccessibilityFeature + * 无障碍特征之字体加粗 */ void OhosAccessibilityFeatures::SetBoldText(double fontWeightScale, int64_t shell_holder_id) { bool shouldBold = fontWeightScale > 1.0; - if (shouldBold) { accessibilityFeatureFlags |= - static_cast(flutter::AccessibilityFeatureFlag::kBoldText); + static_cast(AccessibilityFeatures::BoldText); FML_DLOG(INFO) << "SetBoldText -> accessibilityFeatureFlags: " << accessibilityFeatureFlags; } else { accessibilityFeatureFlags &= - static_cast(flutter::AccessibilityFeatureFlag::kBoldText); + static_cast(AccessibilityFeatures::BoldText); } - SendAccessibilityFlags(shell_holder_id); } @@ -52,7 +67,7 @@ void OhosAccessibilityFeatures::SetBoldText(double fontWeightScale, */ void OhosAccessibilityFeatures::SendAccessibilityFlags( int64_t shell_holder_id) { - auto nativeAccessibilityChannel_ = std::make_shared(); + nativeAccessibilityChannel_ = std::make_shared(); nativeAccessibilityChannel_->SetAccessibilityFeatures(shell_holder_id, accessibilityFeatureFlags); FML_DLOG(INFO) << "SendAccessibilityFlags -> accessibilityFeatureFlags = " << accessibilityFeatureFlags; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_features.h b/shell/platform/ohos/accessibility/ohos_accessibility_features.h index af271318e1..1163180d65 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_features.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_features.h @@ -18,26 +18,41 @@ #include "flutter/lib/ui/window/platform_configuration.h" #include "native_accessibility_channel.h" #include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" - namespace flutter { class OhosAccessibilityFeatures { public: OhosAccessibilityFeatures(); ~OhosAccessibilityFeatures(); + + bool ACCESSIBLE_NAVIGATION = false; - static OhosAccessibilityFeatures* GetInstance(); - + void SetAccessibleNavigation(bool isAccessibleNavigation, + int64_t shell_holder_id); void SetBoldText(double fontWeightScale, int64_t shell_holder_id); + void SendAccessibilityFlags(int64_t shell_holder_id); private: - static OhosAccessibilityFeatures instance; std::shared_ptr nativeAccessibilityChannel_; - int32_t accessibilityFeatureFlags = 0; }; +/** + * 无障碍特征枚举类(flutter平台通用) + * 注意:必须同src/flutter/lib/ui/window/platform_configuration.h + * 中的`AccessibilityFeatureFlag`枚举类保持一致 + */ +enum AccessibilityFeatures : int32_t { + AccessibleNavigation = 1 << 0, + InvertColors = 1 << 1, + DisableAnimations = 1 << 2, + BoldText = 1 << 3, + ReduceMotion = 1 << 4, + HighContrast = 1 << 5, + OnOffSwitchLabels = 1 << 6, +}; + } // namespace flutter #endif \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets index 869e9148fa..cac6460d74 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets @@ -387,7 +387,7 @@ export class FlutterAbility extends UIAbility implements Host { .send(); //热启动生命周期内,实时监听系统设置环境改变并实时发送相应信息 //实时获取系统字体加粗系数 - this.delegate?.getFlutterNapi()?.setFontWeightScale(config.fontWeightScale == undefined? 0 : config.fontWeightScale); + this.delegate?.getFlutterNapi()?.setFontWeightScale(config.fontWeightScale == undefined? 1.0 : config.fontWeightScale); Log.i(TAG, 'fontWeightScale: ' + JSON.stringify(config.fontWeightScale)); if (config.language != '') { diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index 06a086d5db..990cd80f88 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1981,9 +1981,8 @@ napi_value PlatformViewOHOSNapi::nativeSetFontWeightScale(napi_env env, napi_cal << ret; return nullptr; } - // accessibility features get the params - auto ohosAccessibilityFeatures = OhosAccessibilityFeatures::GetInstance(); - ohosAccessibilityFeatures->SetBoldText(fontWeightScale, shell_holder); + auto accessibilityFeatures = std::make_shared(); + accessibilityFeatures->SetBoldText(fontWeightScale, shell_holder); FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeSetFontWeightScale -> shell_holder: " << shell_holder << " fontWeightScale: "<< fontWeightScale; -- Gitee From 5cf5a5a7aae48787fabeb8917435b459904273ce Mon Sep 17 00:00:00 2001 From: hezhengyi Date: Sat, 2 Nov 2024 14:39:12 +0800 Subject: [PATCH 095/151] =?UTF-8?q?=E6=94=AF=E6=8C=81ohos=E6=A8=A1?= =?UTF-8?q?=E6=8B=9F=E5=99=A8=E4=BD=BF=E7=94=A8=E7=89=A9=E7=90=86=E9=94=AE?= =?UTF-8?q?=E7=9B=98=E8=BE=93=E5=85=A5=E5=AD=97=E6=AF=8D=E6=95=B0=E5=AD=97?= =?UTF-8?q?=E5=92=8C=E7=89=B9=E6=AE=8A=E7=AC=A6=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hezhengyi --- .../systemchannels/TextInputChannel.ets | 5 +- .../ohos/FlutterAbilityAndEntryDelegate.ets | 4 - .../ohos/KeyEventHandlerForEmulator.ets | 171 ++++++++++++++++++ .../ets/embedding/ohos/KeyboardManager.ets | 7 +- .../ets/plugin/editing/TextInputPlugin.ets | 8 + .../flutter/src/main/ets/view/FlutterView.ets | 6 +- 6 files changed, 193 insertions(+), 8 deletions(-) create mode 100644 shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyEventHandlerForEmulator.ets diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets index 99a9d4f39c..2515a63c43 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets @@ -40,9 +40,10 @@ export default class TextInputChannel { this.channel = new MethodChannel(dartExecutor, TextInputChannel.CHANNEL_NAME, JSONMethodCodec.INSTANCE); } - setTextInputMethodHandler(textInputMethodHandler: TextInputMethodHandler): void { + setTextInputMethodHandler(textInputMethodHandler: TextInputMethodHandler | null): void { this.textInputMethodHandler = textInputMethodHandler; - this.channel.setMethodCallHandler(new TextInputCallback(this.textInputMethodHandler)); + this.channel.setMethodCallHandler(textInputMethodHandler == null + ? null : new TextInputCallback(textInputMethodHandler)); } requestExistingInputState(): void { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbilityAndEntryDelegate.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbilityAndEntryDelegate.ets index 480371d807..48e85d9b34 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbilityAndEntryDelegate.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbilityAndEntryDelegate.ets @@ -27,7 +27,6 @@ import FlutterInjector from '../../FlutterInjector'; import UIAbility from '@ohos.app.ability.UIAbility'; import ExclusiveAppComponent from './ExclusiveAppComponent'; import AbilityConstant from '@ohos.app.ability.AbilityConstant'; -import TextInputPlugin from '../../plugin/editing/TextInputPlugin'; import { FlutterPlugin } from '../engine/plugins/FlutterPlugin'; import FlutterEngineCache from '../engine/FlutterEngineCache'; import FlutterEngineGroupCache from '../engine/FlutterEngineGroupCache'; @@ -51,7 +50,6 @@ class FlutterAbilityAndEntryDelegate implements ExclusiveAppComponent flutterEngine?: FlutterEngine | null; platformPlugin?: PlatformPlugin; protected context?: common.Context; - protected textInputPlugin?: TextInputPlugin; protected isFlutterEngineFromHostOrCache: boolean = false; private engineGroup?: FlutterEngineGroup; private isHost:boolean = false; @@ -87,7 +85,6 @@ class FlutterAbilityAndEntryDelegate implements ExclusiveAppComponent //configureFlutterEngine this.isAttached = true; if (this.flutterEngine) { - this.textInputPlugin = new TextInputPlugin(this.flutterEngine.getTextInputChannel()!); this.flutterEngine.getSystemLanguages(); } if (this.flutterEngine && this.flutterView && this.host?.attachToEngineAutomatically()) { @@ -271,7 +268,6 @@ class FlutterAbilityAndEntryDelegate implements ExclusiveAppComponent release() { this.host = null; this.flutterEngine = null; - this.textInputPlugin = undefined; this.platformPlugin = undefined; } diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyEventHandlerForEmulator.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyEventHandlerForEmulator.ets new file mode 100644 index 0000000000..34e179d714 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyEventHandlerForEmulator.ets @@ -0,0 +1,171 @@ +/* + * 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 { HashMap } from "@kit.ArkTS"; +import deviceInfo from '@ohos.deviceInfo'; +import TextInputPlugin from "../../plugin/editing/TextInputPlugin"; +import Log from "../../util/Log"; +import { KeyCode } from "@kit.InputKit"; + +const TAG = "KeyEventHandlerForEmulator"; + +export class KeyEventHandlerForEmulator { + private textInputPlugin?: TextInputPlugin; + private charMap : HashMap = new HashMap(); + private shiftMap : HashMap = new HashMap(); + private isShiftMode: boolean = false; + + constructor(textInputPlugin?: TextInputPlugin) { + this.textInputPlugin = textInputPlugin; + this.initCharMap(); + this.initShiftMap(); + } + + private initCharMap() { + this.charMap.set(KeyCode.KEYCODE_0, '0') + this.charMap.set(KeyCode.KEYCODE_1, '1') + this.charMap.set(KeyCode.KEYCODE_2, '2') + this.charMap.set(KeyCode.KEYCODE_3, '3') + this.charMap.set(KeyCode.KEYCODE_4, '4') + this.charMap.set(KeyCode.KEYCODE_5, '5') + this.charMap.set(KeyCode.KEYCODE_6, '6') + this.charMap.set(KeyCode.KEYCODE_7, '7') + this.charMap.set(KeyCode.KEYCODE_8, '8') + this.charMap.set(KeyCode.KEYCODE_9, '9') + this.charMap.set(KeyCode.KEYCODE_A, 'a') + this.charMap.set(KeyCode.KEYCODE_B, 'b') + this.charMap.set(KeyCode.KEYCODE_C, 'c') + this.charMap.set(KeyCode.KEYCODE_D, 'd') + this.charMap.set(KeyCode.KEYCODE_E, 'e') + this.charMap.set(KeyCode.KEYCODE_F, 'f') + this.charMap.set(KeyCode.KEYCODE_G, 'g') + this.charMap.set(KeyCode.KEYCODE_H, 'h') + this.charMap.set(KeyCode.KEYCODE_I, 'i') + this.charMap.set(KeyCode.KEYCODE_J, 'j') + this.charMap.set(KeyCode.KEYCODE_K, 'k') + this.charMap.set(KeyCode.KEYCODE_L, 'l') + this.charMap.set(KeyCode.KEYCODE_M, 'm') + this.charMap.set(KeyCode.KEYCODE_N, 'n') + this.charMap.set(KeyCode.KEYCODE_O, 'o') + this.charMap.set(KeyCode.KEYCODE_P, 'p') + this.charMap.set(KeyCode.KEYCODE_Q, 'q') + this.charMap.set(KeyCode.KEYCODE_R, 'r') + this.charMap.set(KeyCode.KEYCODE_S, 's') + this.charMap.set(KeyCode.KEYCODE_T, 't') + this.charMap.set(KeyCode.KEYCODE_U, 'u') + this.charMap.set(KeyCode.KEYCODE_V, 'v') + this.charMap.set(KeyCode.KEYCODE_W, 'w') + this.charMap.set(KeyCode.KEYCODE_X, 'x') + this.charMap.set(KeyCode.KEYCODE_Y, 'y') + this.charMap.set(KeyCode.KEYCODE_Z, 'z') + this.charMap.set(KeyCode.KEYCODE_GRAVE, '`') + this.charMap.set(KeyCode.KEYCODE_MINUS, '-') + this.charMap.set(KeyCode.KEYCODE_EQUALS, '=') + this.charMap.set(KeyCode.KEYCODE_LEFT_BRACKET, '[') + this.charMap.set(KeyCode.KEYCODE_RIGHT_BRACKET, ']') + this.charMap.set(KeyCode.KEYCODE_BACKSLASH, '\\') + this.charMap.set(KeyCode.KEYCODE_SEMICOLON, ';') + this.charMap.set(KeyCode.KEYCODE_APOSTROPHE, '\'') + this.charMap.set(KeyCode.KEYCODE_COMMA, ',') + this.charMap.set(KeyCode.KEYCODE_PERIOD, '.') + this.charMap.set(KeyCode.KEYCODE_SLASH, '/') + this.charMap.set(KeyCode.KEYCODE_SPACE, ' ') + } + + private initShiftMap() { + this.shiftMap.set(KeyCode.KEYCODE_0, ')') + this.shiftMap.set(KeyCode.KEYCODE_1, '!') + this.shiftMap.set(KeyCode.KEYCODE_2, '@') + this.shiftMap.set(KeyCode.KEYCODE_3, '#') + this.shiftMap.set(KeyCode.KEYCODE_4, '$') + this.shiftMap.set(KeyCode.KEYCODE_5, '%') + this.shiftMap.set(KeyCode.KEYCODE_6, '^') + this.shiftMap.set(KeyCode.KEYCODE_7, '&') + this.shiftMap.set(KeyCode.KEYCODE_8, '*') + this.shiftMap.set(KeyCode.KEYCODE_9, '(') + this.shiftMap.set(KeyCode.KEYCODE_A, 'A') + this.shiftMap.set(KeyCode.KEYCODE_B, 'B') + this.shiftMap.set(KeyCode.KEYCODE_C, 'C') + this.shiftMap.set(KeyCode.KEYCODE_D, 'D') + this.shiftMap.set(KeyCode.KEYCODE_E, 'E') + this.shiftMap.set(KeyCode.KEYCODE_F, 'F') + this.shiftMap.set(KeyCode.KEYCODE_G, 'G') + this.shiftMap.set(KeyCode.KEYCODE_H, 'H') + this.shiftMap.set(KeyCode.KEYCODE_I, 'I') + this.shiftMap.set(KeyCode.KEYCODE_J, 'J') + this.shiftMap.set(KeyCode.KEYCODE_K, 'K') + this.shiftMap.set(KeyCode.KEYCODE_L, 'L') + this.shiftMap.set(KeyCode.KEYCODE_M, 'M') + this.shiftMap.set(KeyCode.KEYCODE_N, 'N') + this.shiftMap.set(KeyCode.KEYCODE_O, 'O') + this.shiftMap.set(KeyCode.KEYCODE_P, 'P') + this.shiftMap.set(KeyCode.KEYCODE_Q, 'Q') + this.shiftMap.set(KeyCode.KEYCODE_R, 'R') + this.shiftMap.set(KeyCode.KEYCODE_S, 'S') + this.shiftMap.set(KeyCode.KEYCODE_T, 'T') + this.shiftMap.set(KeyCode.KEYCODE_U, 'U') + this.shiftMap.set(KeyCode.KEYCODE_V, 'V') + this.shiftMap.set(KeyCode.KEYCODE_W, 'W') + this.shiftMap.set(KeyCode.KEYCODE_X, 'X') + this.shiftMap.set(KeyCode.KEYCODE_Y, 'Y') + this.shiftMap.set(KeyCode.KEYCODE_Z, 'Z') + this.shiftMap.set(KeyCode.KEYCODE_GRAVE, '~') + this.shiftMap.set(KeyCode.KEYCODE_MINUS, '_') + this.shiftMap.set(KeyCode.KEYCODE_EQUALS, '+') + this.shiftMap.set(KeyCode.KEYCODE_LEFT_BRACKET, '{') + this.shiftMap.set(KeyCode.KEYCODE_RIGHT_BRACKET, '}') + this.shiftMap.set(KeyCode.KEYCODE_BACKSLASH, '|') + this.shiftMap.set(KeyCode.KEYCODE_SEMICOLON, ':') + this.shiftMap.set(KeyCode.KEYCODE_APOSTROPHE, '"') + this.shiftMap.set(KeyCode.KEYCODE_COMMA, '<') + this.shiftMap.set(KeyCode.KEYCODE_PERIOD, '>') + this.shiftMap.set(KeyCode.KEYCODE_SLASH, '?') + this.shiftMap.set(KeyCode.KEYCODE_SPACE, ' ') + } + + getCharByEvent(event: KeyEvent) : string { + let key = event.keyCode; + if (this.isShiftMode) { + return this.shiftMap.hasKey(key) ? this.shiftMap.get(key) : '' + } else { + return this.charMap.hasKey(key) ? this.charMap.get(key) : '' + } + } + + isEmulator() : boolean { + return deviceInfo.productModel == 'emulator'; + } + + handleKeyEvent(event: KeyEvent) { + Log.i(TAG, JSON.stringify({ + "name": "handleKeyEvent", + "event": event + })); + if (!this.isEmulator()) { + return; + } + if (event.type == KeyType.Up) { + // 处理字符按键相关逻辑 + if (this.charMap.hasKey(event.keyCode)) { + this.textInputPlugin?.getEditingState().handleInsertTextEvent(this.getCharByEvent(event)) + } + // 处理非字符按键 + if (event.keyCode == KeyCode.KEYCODE_DEL) { + this.textInputPlugin?.getEditingState().handleDeleteEvent(false, 0) + } + } + this.isShiftMode = event.keyCode == KeyCode.KEYCODE_SHIFT_LEFT + } +} diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyboardManager.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyboardManager.ets index ec4a02ff78..0951c126fb 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyboardManager.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyboardManager.ets @@ -12,14 +12,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import TextInputPlugin from '../../plugin/editing/TextInputPlugin'; import FlutterEngine from '../engine/FlutterEngine'; import KeyEventChannel, { FlutterKeyEvent } from '../engine/systemchannels/KeyEventChannel'; +import { KeyEventHandlerForEmulator } from './KeyEventHandlerForEmulator'; export default class KeyboardManager { private keyEventChannel: KeyEventChannel | null = null + private keyEventHandlerForEmulator: KeyEventHandlerForEmulator; - constructor(engine: FlutterEngine) { + constructor(engine: FlutterEngine, textInputPlugin: TextInputPlugin) { this.keyEventChannel = new KeyEventChannel(engine.dartExecutor) + this.keyEventHandlerForEmulator = new KeyEventHandlerForEmulator(textInputPlugin); } handleKeyEvent(event: KeyEvent) { @@ -28,5 +32,6 @@ export default class KeyboardManager { } }) + this.keyEventHandlerForEmulator.handleKeyEvent(event); } } \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets index c64f1d88f9..5f3a67c362 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/editing/TextInputPlugin.ets @@ -46,6 +46,10 @@ export default class TextInputPlugin implements EditingStateWatcher { } + getEditingState() { + return this.mTextInputHandler.mEditable; + } + didChangeEditingState(textChanged: boolean, selectionChanged: boolean, composingRegionChanged: boolean): void { let editable = this.mTextInputHandler.mEditable; let inputTarget = this.mTextInputHandler.inputTarget; @@ -68,6 +72,10 @@ export default class TextInputPlugin implements EditingStateWatcher { } }) } + + destroy() { + this.textInputChannel.setTextInputMethodHandler(null); + } } class TextInputMethodHandlerImpl implements TextInputMethodHandler { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index 5af7b9cf9d..aeb9518b6a 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -25,6 +25,7 @@ import ArrayList from '@ohos.util.ArrayList'; import { EmbeddingNodeController } from '../embedding/ohos/EmbeddingNodeController'; import PlatformView, { Params } from '../plugin/platform/PlatformView'; import { JSON } from '@kit.ArkTS'; +import TextInputPlugin from '../plugin/editing/TextInputPlugin'; const TAG = "FlutterViewTag"; @@ -120,6 +121,7 @@ export class FlutterView { private keyboardManager: KeyboardManager | null = null; private mainWindow: window.Window | null = null; private mouseCursorPlugin?: MouseCursorPlugin; + private textInputPlugin?: TextInputPlugin; private uiContext?: UIContext | undefined; private settings?: Settings; private mFirstFrameListeners: ArrayList; @@ -285,7 +287,6 @@ export class FlutterView { } Log.i(TAG, "attachToFlutterEngine"); this.flutterEngine = flutterEngine; - this.keyboardManager = new KeyboardManager(flutterEngine); if (this.isSurfaceAvailableForRendering) { this.flutterEngine.getFlutterNapi().xComponentAttachFlutterEngine(this.id) } @@ -306,6 +307,8 @@ export class FlutterView { let windowId = this.mainWindow?.getWindowProperties()?.id ?? 0 this.mouseCursorPlugin = new MouseCursorPlugin(windowId, this.flutterEngine?.getMouseCursorChannel()!); + this.textInputPlugin = new TextInputPlugin(this.flutterEngine?.getTextInputChannel()!); + this.keyboardManager = new KeyboardManager(flutterEngine, this.textInputPlugin!); this.settings = new Settings(this.flutterEngine.getSettingsChannel()!); this.sendSettings(); this.isFlutterUiDisplayed = this.flutterEngine.getFlutterNapi().isDisplayingFlutterUi; @@ -327,6 +330,7 @@ export class FlutterView { this.flutterEngine?.getPlatformViewsController()?.detachFromView(); this.flutterEngine = null; this.keyboardManager = null; + this.textInputPlugin?.destroy(); } onWindowCreated() { -- Gitee From 89eb30994048c713dbc95d7affe5529079e50bfa Mon Sep 17 00:00:00 2001 From: zjxi Date: Tue, 5 Nov 2024 17:19:39 +0800 Subject: [PATCH 096/151] =?UTF-8?q?refactor:=E5=B0=81=E8=A3=85=E6=9E=84?= =?UTF-8?q?=E5=BB=BAarkui=E6=97=A0=E9=9A=9C=E7=A2=8D=E8=AF=AD=E4=B9=89?= =?UTF-8?q?=E6=A0=91=E4=BB=A3=E7=A0=81=E9=80=BB=E8=BE=91,=E5=87=8F?= =?UTF-8?q?=E5=B0=91=E5=86=97=E4=BD=99=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 71 ++++++++++--------- .../accessibility/ohos_accessibility_bridge.h | 4 ++ 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index f463cf2e69..dfee673775 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -545,7 +545,7 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( // 获取root节点的绝对坐标, 即xcomponent屏幕长宽 auto _rootRect = GetAbsoluteScreenRect(0); - // float rootWidth = _rootRect.second.first; + float rootWidth = _rootRect.second.first; auto rootHeight = _rootRect.second.second; // 真实缩放系数 @@ -585,9 +585,9 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( << currNode.id << ", (" << newLeft << ", " << newTop << ", " << newRight << ", " << newBottom << ")}"; // 防止滑动场景下绿框坐标超出屏幕范围,进行正则化处理 - // newLeft = static_cast(newLeft) % static_cast(rootWidth); + newLeft = static_cast(newLeft) % static_cast(rootWidth); newTop = static_cast(newTop) % static_cast(rootHeight); - // newRight = static_cast(newRight) % static_cast(rootWidth); + newRight = static_cast(newRight) % static_cast(rootWidth); newBottom = static_cast(newBottom) % static_cast(rootHeight); SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); @@ -612,8 +612,8 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( "elementInfoFromList is null"; return; } - - /** NOTE: when elementId == 0 || elementId == -1 */ + FML_DLOG(INFO) << "FlutterNodeToElementInfoById elementId = " << elementId; + // 当elementId = -1或0时,创建root节点 if (elementId == 0 || elementId == -1) { // 获取flutter的root节点 flutter::SemanticsNode flutterNode = @@ -670,15 +670,10 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root"); OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, flutterNode.label.c_str()); - return; + } else { + //当elementId >= 1时,根据flutter节点信息配置elementinfo无障碍属性 + FlutterSetElementInfoProperties(elementInfoFromList, elementId); } - - /** NOTE: when elementId >= 1 */ - FML_DLOG(INFO) << "FlutterNodeToElementInfoById elementId = " << elementId; - - // 根据flutter节点信息配置elementinfo无障碍属性 - FlutterSetElementInfoProperties(elementInfoFromList, elementId); - FML_DLOG(INFO) << "=== OhosAccessibilityBridge::FlutterNodeToElementInfoById is end ==="; } @@ -986,6 +981,32 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( false); } +/** + * 创建并配置完整arkui无障碍语义树 + */ +void OhosAccessibilityBridge::BuildArkUISemanticsTree( + int64_t elementId, + ArkUI_AccessibilityElementInfo* elementInfoFromList, + ArkUI_AccessibilityElementInfoList* elementList) +{ + //配置root节点信息 + FlutterNodeToElementInfoById(elementInfoFromList, elementId); + //获取flutter无障碍语义树的节点总数 + int64_t elementInfoCount = + static_cast(flutterSemanticsTree_.size()); + //创建并配置节点id >= 1的全部节点 + for (int64_t i = elementId + 1; i < elementInfoCount; i++) { + auto childNode = GetFlutterSemanticsNode(static_cast(i)); + //当节点为隐藏状态时,自动规避 + if (IsNodeVisible(childNode)) { + ArkUI_AccessibilityElementInfo* newElementInfo = + OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + //配置当前子节点信息 + FlutterNodeToElementInfoById(newElementInfo, i); + } + } +} + /** * Called to obtain element information based on a specified node. * NOTE:该arkui接口需要在系统无障碍服务开启时,才能触发调用 @@ -1035,17 +1056,7 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( if (mode == ArkUI_AccessibilitySearchMode:: ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { /** Search for current nodes. (mode = 0) */ - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - int64_t elementInfoCount = - static_cast(flutterSemanticsTree_.size()); - for (int64_t i = 1; i < elementInfoCount; i++) { - auto childNode = GetFlutterSemanticsNode(static_cast(i)); - if (IsNodeVisible(childNode)) { - ArkUI_AccessibilityElementInfo* newElementInfo = - OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); - FlutterNodeToElementInfoById(newElementInfo, i); - } - } + BuildArkUISemanticsTree(elementId, elementInfoFromList, elementList); } else if (mode == ArkUI_AccessibilitySearchMode:: ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS) { @@ -1072,17 +1083,7 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( ArkUI_AccessibilitySearchMode:: ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_RECURSIVE_CHILDREN) { /** Search for all child nodes. (mode = 8) */ - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - int64_t elementInfoCount = - static_cast(flutterSemanticsTree_.size()); - for (int64_t i = 1; i < elementInfoCount; i++) { - auto childNode = GetFlutterSemanticsNode(static_cast(i)); - if (IsNodeVisible(childNode)) { - ArkUI_AccessibilityElementInfo* newElementInfo = - OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); - FlutterNodeToElementInfoById(newElementInfo, i); - } - } + BuildArkUISemanticsTree(elementId, elementInfoFromList, elementList); } else { if (IsNodeVisible(flutterNode)) { FlutterNodeToElementInfoById(elementInfoFromList, elementId); diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 7a669b53e4..64d717a7a9 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -230,6 +230,10 @@ class OhosAccessibilityBridge { std::string widget_type); void FlutterTreeToArkuiTree( ArkUI_AccessibilityElementInfoList* elementInfoList); + void BuildArkUISemanticsTree( + int64_t elementId, + ArkUI_AccessibilityElementInfo* elementInfoFromList, + ArkUI_AccessibilityElementInfoList* elementList); flutter::SemanticsNode GetFlutterRootSemanticsNode(); std::string GetNodeComponentType(const flutter::SemanticsNode& node); -- Gitee From 9515931232f1a54dea40b3ca6962efaba24df168 Mon Sep 17 00:00:00 2001 From: laoguanyao <806103474@qq.com> Date: Thu, 7 Nov 2024 08:25:56 +0800 Subject: [PATCH 097/151] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BC=98=E5=85=88?= =?UTF-8?q?=E6=94=B6=E8=B5=B7=E8=BD=AF=E9=94=AE=E7=9B=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: laoguanyao <806103474@qq.com> --- .../src/main/ets/embedding/ohos/FlutterAbility.ets | 10 ++++++++-- .../flutter/src/main/ets/view/FlutterView.ets | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets index af3a61cd6d..6863ccbb79 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets @@ -37,6 +37,7 @@ import FlutterManager from './FlutterManager'; import { FlutterView } from '../../view/FlutterView'; import ApplicationInfoLoader from '../engine/loader/ApplicationInfoLoader'; import { AccessibilityManager } from '../../view/AccessibilityBridge'; +import inputMethod from '@ohos.inputMethod'; const TAG = "FlutterAbility"; const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS'; @@ -53,6 +54,7 @@ export class FlutterAbility extends UIAbility implements Host { private mainWindow?: window.Window | null; private errorManagerId:number = 0; private accessibilityManager?: AccessibilityManager | null; + private inputMethodController: inputMethod.InputMethodController = inputMethod.getController(); getFlutterView(): FlutterView | null { return this.flutterView; @@ -93,8 +95,12 @@ export class FlutterAbility extends UIAbility implements Host { Log.i(TAG, 'MyAbility onCreate'); this.context.eventHub.on(EVENT_BACK_PRESS, () => { - this.delegate?.flutterEngine?.getNavigationChannel()?.popRoute(); - this.delegate?.flutterEngine?.getPlatformViewsController()?.setBackNodeControllers(); + if (this.flutterView?.getKeyboardHeight() == 0) { + this.delegate?.flutterEngine?.getNavigationChannel()?.popRoute(); + this.delegate?.flutterEngine?.getPlatformViewsController()?.setBackNodeControllers(); + } else { + this.inputMethodController.detach(); + } }); let observer:errorManager.ErrorObserver = { onUnhandledException(errorMsg) { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index 5af7b9cf9d..f0ff44d2b1 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -247,6 +247,10 @@ export class FlutterView { return this.dVModel } + getKeyboardHeight() { + return this.keyboardAvoidArea.bottomRect.height + } + onDestroy() { try { this.mainWindow?.off('windowSizeChange', this.windowSizeChangeCallback); -- Gitee From 552b40d63400539dda72b384432c2610a45088fc Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 7 Nov 2024 11:03:30 +0800 Subject: [PATCH 098/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E6=94=B9?= =?UTF-8?q?=E8=BF=9B=E7=89=88=E5=B1=82=E6=AC=A1=E9=81=8D=E5=8E=86=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E6=9E=84=E5=BB=BAarkui=E6=A0=91,=E4=BB=A5=E6=8E=A5?= =?UTF-8?q?=E5=85=A5Hypium=E5=92=8CUIViewer=E8=87=AA=E5=8A=A8=E5=8C=96?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=A1=86=E6=9E=B6,=E5=AE=9E=E7=8E=B0flutter?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E6=A0=91=E7=9A=84=E5=8F=AF=E8=A7=86=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 136 ++++++++---------- .../accessibility/ohos_accessibility_bridge.h | 5 +- 2 files changed, 66 insertions(+), 75 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index dfee673775..e0836cecbb 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -54,10 +54,8 @@ void OhosAccessibilityBridge::OnOhosAccessibilityStateChange( accessibilityFeatures_ = std::make_shared(); if (ohosAccessibilityEnabled) { - FML_DLOG(INFO) << "OnOhosAccessibilityEnabled()"; nativeAccessibilityChannel_->OnOhosAccessibilityEnabled(native_shell_holder_id_); } else { - FML_DLOG(INFO) << "OnOhosAccessibilityEnabled()"; accessibilityFeatures_->SetAccessibleNavigation(false, native_shell_holder_id_); nativeAccessibilityChannel_->OnOhosAccessibilityDisabled(native_shell_holder_id_); } @@ -75,7 +73,7 @@ void OhosAccessibilityBridge::updateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { - FML_DLOG(INFO) << ("OhosAccessibilityBridge::updateSemantics is called"); + FML_DLOG(INFO) << ("OhosAccessibilityBridge::UpdateSemantics()"); // 当flutter页面更新时,自动请求id=0节点组件获焦(滑动组件除外) if (IS_FLUTTER_NAVIGATE) { @@ -147,6 +145,11 @@ void OhosAccessibilityBridge::updateSemantics( << item.second << ")"; } + //打印按层次遍历排序的flutter语义树节点id数组 + std::vector levelOrderTraversalTree = GetLevelOrderTraversalTree(0); + for (const auto& item: levelOrderTraversalTree) { + FML_DLOG(INFO) << "LevelOrderTraversalTree: { " << item << " }"; + } FML_DLOG(INFO) << "=== UpdateSemantics is end ==="; } @@ -225,27 +228,20 @@ void OhosAccessibilityBridge::FlutterScrollExecution( } /** - * 当页面状态更新事件,在页面转换、切换、调整大小时发送页面状态更新事件 + * 当页面内容/状态更新事件,在页面转换、切换、调整大小时发送页面状态更新事件 */ -void OhosAccessibilityBridge::PageStateUpdate() +void OhosAccessibilityBridge::FlutterPageUpdate( + ArkUI_AccessibilityEventType eventType) { ArkUI_AccessibilityEventInfo* pageUpdateEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); - ArkUI_AccessibilityElementInfo* _elementInfo = - OH_ArkUI_CreateAccessibilityElementInfo(); - OH_ArkUI_AccessibilityEventSetEventType( - pageUpdateEventInfo, - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); - // FlutterNodeToElementInfoById(_elementInfo, elementId); - OH_ArkUI_AccessibilityEventSetElementInfo(pageUpdateEventInfo, _elementInfo); + pageUpdateEventInfo, eventType); auto callback = [](int32_t errorCode) { FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; }; - if (provider_ == nullptr) { FML_DLOG(ERROR) << "PageStateUpdate ->" "AccessibilityProvider = nullptr"; @@ -253,9 +249,7 @@ void OhosAccessibilityBridge::PageStateUpdate() } OH_ArkUI_SendAccessibilityAsyncEvent(provider_, pageUpdateEventInfo, callback); - OH_ArkUI_DestoryAccessibilityEventInfo(pageUpdateEventInfo); - OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); FML_DLOG(INFO) << "PageStateUpdate is end"; } @@ -422,12 +416,12 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( } // 设置孩子节点 - int32_t childCount = - static_cast(flutterNode.childrenInTraversalOrder.size()); + int32_t childCount = flutterNode.childrenInTraversalOrder.size(); + auto childrenIdsVec = flutterNode.childrenInTraversalOrder; + std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); int64_t childNodeIds[childCount]; for (int32_t i = 0; i < childCount; i++) { - childNodeIds[i] = - static_cast(flutterNode.childrenInTraversalOrder[i]); + childNodeIds[i] = static_cast(childrenIdsVec[i]); FML_DLOG(INFO) << "FlutterTreeToArkuiTree flutterNode.id= " << flutterNode.id << " childCount= " << childCount << " childNodeId=" << childNodeIds[i]; @@ -648,13 +642,12 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( false); // 配置child节点信息 - auto flutterChildVec = flutterNode.childrenInTraversalOrder; - int32_t childCount = - static_cast(flutterChildVec.size()); + int32_t childCount = flutterNode.childrenInTraversalOrder.size(); + auto childrenIdsVec = flutterNode.childrenInTraversalOrder; + std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); int64_t childNodeIds[childCount]; for (int32_t i = 0; i < childCount; i++) { - childNodeIds[i] = - static_cast(flutterChildVec[i]); + childNodeIds[i] = static_cast(childrenIdsVec[i]); FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> elementid=0 childCount=" << childCount << " childNodeIds=" << childNodeIds[i]; @@ -859,15 +852,12 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( hint.c_str()); // set chidren elementinfo ids - auto flutterChildVec = flutterNode.childrenInTraversalOrder; - //按照升序排列孩子数组id - std::sort(flutterChildVec.begin(), flutterChildVec.end()); - int32_t childCount = - static_cast(flutterChildVec.size()); + int32_t childCount = flutterNode.childrenInTraversalOrder.size(); + auto childrenIdsVec = flutterNode.childrenInTraversalOrder; + std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); int64_t childNodeIds[childCount]; for (int32_t i = 0; i < childCount; i++) { - childNodeIds[i] = - static_cast(flutterChildVec[i]); + childNodeIds[i] = static_cast(childrenIdsVec[i]); FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> elementid=" << elementId << " childCount=" << childCount << " childNodeIds=" << childNodeIds[i]; @@ -981,6 +971,37 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( false); } +/** + * 将flutter无障碍语义树的转化为层次遍历顺序存储, + * 并按该顺序构建arkui语义树,以实现DevEco Testing + * UIViewer、Hypium自动化测试工具对flutter组件树的可视化 + */ +std::vector OhosAccessibilityBridge::GetLevelOrderTraversalTree(int32_t rootId) +{ + std::vector levelOrderTraversalTree; + std::queue semanticsQue; + + auto root = GetFlutterSemanticsNode(rootId); + semanticsQue.push(root); + + while (!semanticsQue.empty()) { + uint32_t queSize = semanticsQue.size(); + for (uint32_t i=0; i(currNode.id)); + + std::sort(currNode.childrenInTraversalOrder.begin(), + currNode.childrenInTraversalOrder.end()); + for(auto& childId: currNode.childrenInTraversalOrder) { + auto childNode = GetFlutterSemanticsNode(childId); + semanticsQue.push(childNode); + } + } + } + return levelOrderTraversalTree; +} + /** * 创建并配置完整arkui无障碍语义树 */ @@ -992,17 +1013,18 @@ void OhosAccessibilityBridge::BuildArkUISemanticsTree( //配置root节点信息 FlutterNodeToElementInfoById(elementInfoFromList, elementId); //获取flutter无障碍语义树的节点总数 - int64_t elementInfoCount = - static_cast(flutterSemanticsTree_.size()); + auto levelOrderTreeVec = GetLevelOrderTraversalTree(0); + int64_t elementInfoCount = levelOrderTreeVec.size(); //创建并配置节点id >= 1的全部节点 - for (int64_t i = elementId + 1; i < elementInfoCount; i++) { - auto childNode = GetFlutterSemanticsNode(static_cast(i)); + for (int64_t i = 1; i < elementInfoCount; i++) { + int64_t levelOrderId = levelOrderTreeVec[i]; + auto newNode = GetFlutterSemanticsNode(levelOrderId); //当节点为隐藏状态时,自动规避 - if (IsNodeVisible(childNode)) { + if (IsNodeVisible(newNode)) { ArkUI_AccessibilityElementInfo* newElementInfo = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); //配置当前子节点信息 - FlutterNodeToElementInfoById(newElementInfo, i); + FlutterNodeToElementInfoById(newElementInfo, levelOrderId); } } } @@ -1085,9 +1107,7 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( /** Search for all child nodes. (mode = 8) */ BuildArkUISemanticsTree(elementId, elementInfoFromList, elementList); } else { - if (IsNodeVisible(flutterNode)) { - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - } + FlutterNodeToElementInfoById(elementInfoFromList, elementId); } FML_DLOG(INFO) << "--- FindAccessibilityNodeInfosById is end ---"; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; @@ -1142,14 +1162,12 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( Flutter_SendAccessibilityAsyncEvent(elementId, clickEventType); FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: click(" << action << ")" << " event: click(" << clickEventType << ")"; - // 解析arkui的屏幕点击 -> flutter对应节点的屏幕点击 auto flutterTapAction = ArkuiActionsToFlutterActions(action); DispatchSemanticsAction(static_cast(elementId), flutterTapAction, {}); break; } - /** Response to a long click. 32 */ case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: { @@ -1160,14 +1178,12 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: longclick(" << action << ")" << " event: longclick(" << longClickEventType << ")"; - // 解析arkui的屏幕动作 -> flutter对应节点的屏幕动作 auto flutterLongPressAction = ArkuiActionsToFlutterActions(action); DispatchSemanticsAction(static_cast(elementId), flutterLongPressAction, {}); break; } - /** Accessibility focus acquisition. 64 */ case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: { @@ -1175,8 +1191,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( auto flutterGainFocusAction = ArkuiActionsToFlutterActions(action); DispatchSemanticsAction(static_cast(elementId), flutterGainFocusAction, {}); - /** Accessibility focus event, sent after the UI component responds. 32768 - */ + // Accessibility focus event, sent after the UI component responds. 32768 auto focusEventType = ArkUI_AccessibilityEventType:: ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; Flutter_SendAccessibilityAsyncEvent(elementId, focusEventType); @@ -1190,7 +1205,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( } break; } - /** Accessibility focus clearance. 128 */ case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: { @@ -1198,7 +1212,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( auto flutterLoseFocusAction = ArkuiActionsToFlutterActions(action); DispatchSemanticsAction(static_cast(elementId), flutterLoseFocusAction, {}); - /** Accessibility focus cleared event, sent after the UI component * responds. 65536 */ auto clearFocusEventType = ArkUI_AccessibilityEventType:: @@ -1209,7 +1222,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( << clearFocusEventType << ")"; break; } - /** Forward scroll action. 256 */ case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: { @@ -1218,21 +1230,18 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( auto flutterScrollUpAction = ArkuiActionsToFlutterActions(action); DispatchSemanticsAction(static_cast(elementId), flutterScrollUpAction, {}); - } else if (flutterNode.HasAction(ACTIONS_::kScrollLeft)) { DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kScrollLeft, {}); - } else if (flutterNode.HasAction(ACTIONS_::kIncrease)) { flutterNode.value = flutterNode.increasedValue; flutterNode.valueAttributes = flutterNode.increasedValueAttributes; - + Flutter_SendAccessibilityAsyncEvent( elementId, ArkUI_AccessibilityEventType:: ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kIncrease, {}); - } else { } std::string currComponetType = GetNodeComponentType(flutterNode); @@ -1249,7 +1258,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( } break; } - /** Backward scroll action. 512 */ case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: { @@ -1287,7 +1295,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( } break; } - /** Copy action for text content. 1024 */ case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: { @@ -1297,7 +1304,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( {}); break; } - /** Paste action for text content. 2048 */ case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE: { @@ -1307,7 +1313,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( {}); break; } - /** Cut action for text content. 4096 */ case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: @@ -1316,7 +1321,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCut, {}); break; - /** Text selection action, requiring the setting of selectTextBegin, * TextEnd, and TextInForward parameters to select a text * segment in the text box. 8192 */ @@ -1328,7 +1332,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( PerformSelectText(flutterNode, action, actionArguments); break; } - /** Text content setting action. 16384 */ case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: { @@ -1338,7 +1341,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( PerformSetText(flutterNode, action, actionArguments); break; } - /** Cursor position setting action. 1048576 */ case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION: { @@ -1348,7 +1350,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( // 当前os接口不支持该功能,不影响正常屏幕朗读 break; } - /** Invalid action. 0 */ case ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID: { @@ -1362,7 +1363,6 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( << invalidEventType << ")"; break; } - default: { /** custom semantics action */ } @@ -1581,34 +1581,27 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( if (node.HasFlag(FLAGS_::kIsButton)) { return "Button"; } - if (node.HasFlag(FLAGS_::kIsTextField)) { // arkui没有textfield,这里直接透传或者传递textinput return "TextField"; } - if (node.HasFlag(FLAGS_::kIsMultiline)) { // arkui没有多行文本textfield,这里直接透传 return "TextArea"; } - if (node.HasFlag(FLAGS_::kIsLink)) { return "Link"; } - if (node.HasFlag(FLAGS_::kIsSlider) || node.HasAction(ACTIONS_::kIncrease) || node.HasAction(ACTIONS_::kDecrease)) { return "Slider"; } - if (node.HasFlag(FLAGS_::kIsHeader)) { return "Header"; } - if (node.HasFlag(FLAGS_::kIsImage)) { return "Image"; } - if (node.HasFlag(FLAGS_::kHasCheckedState)) { if (node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup)) { // arkui没有RadioButton,这里透传为RadioButton @@ -1617,16 +1610,13 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( return "Checkbox"; } } - if (node.HasFlag(FLAGS_::kHasToggledState)) { // arkui没有ToggleSwitch,这里透传为Toggle return "ToggleSwitch"; } - if ((!node.label.empty() || !node.tooltip.empty() || !node.hint.empty())) { return "Text"; } - return "Widget" + std::to_string(node.id); } diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 64d717a7a9..1eedd1be56 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -234,7 +234,8 @@ class OhosAccessibilityBridge { int64_t elementId, ArkUI_AccessibilityElementInfo* elementInfoFromList, ArkUI_AccessibilityElementInfoList* elementList); - + + std::vector GetLevelOrderTraversalTree(int32_t rootId); flutter::SemanticsNode GetFlutterRootSemanticsNode(); std::string GetNodeComponentType(const flutter::SemanticsNode& node); flutter::SemanticsAction ArkuiActionsToFlutterActions( @@ -274,7 +275,7 @@ class OhosAccessibilityBridge { void GetCustomActionDebugInfo( flutter::CustomAccessibilityAction customAccessibilityAction); - void PageStateUpdate(); + void FlutterPageUpdate(ArkUI_AccessibilityEventType eventType); void RequestFocusWhenPageUpdate(); bool Contains(const std::string source, const std::string target); -- Gitee From 8380aace8e08989a653392307bde14793f9b49d2 Mon Sep 17 00:00:00 2001 From: laoguanyao <806103474@qq.com> Date: Thu, 7 Nov 2024 20:16:55 +0800 Subject: [PATCH 099/151] =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E7=9B=91=E5=90=AC?= =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E5=88=B0delegate=EF=BC=8C=E4=BB=A5=E9=80=82?= =?UTF-8?q?=E9=85=8DFlutterAbility=E5=92=8CFlutterEntry=E4=B8=A4=E7=A7=8D?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: laoguanyao <806103474@qq.com> --- .../src/main/ets/embedding/ohos/FlutterAbility.ets | 13 +------------ .../ohos/FlutterAbilityAndEntryDelegate.ets | 14 +++++++++++++- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets index 6863ccbb79..8c541c79ba 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbility.ets @@ -37,10 +37,8 @@ import FlutterManager from './FlutterManager'; import { FlutterView } from '../../view/FlutterView'; import ApplicationInfoLoader from '../engine/loader/ApplicationInfoLoader'; import { AccessibilityManager } from '../../view/AccessibilityBridge'; -import inputMethod from '@ohos.inputMethod'; const TAG = "FlutterAbility"; -const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS'; /** * flutter ohos基础ability,请在让主ability继承自该类。 @@ -54,7 +52,6 @@ export class FlutterAbility extends UIAbility implements Host { private mainWindow?: window.Window | null; private errorManagerId:number = 0; private accessibilityManager?: AccessibilityManager | null; - private inputMethodController: inputMethod.InputMethodController = inputMethod.getController(); getFlutterView(): FlutterView | null { return this.flutterView; @@ -94,14 +91,6 @@ export class FlutterAbility extends UIAbility implements Host { Log.i(TAG, 'MyAbility onCreate'); - this.context.eventHub.on(EVENT_BACK_PRESS, () => { - if (this.flutterView?.getKeyboardHeight() == 0) { - this.delegate?.flutterEngine?.getNavigationChannel()?.popRoute(); - this.delegate?.flutterEngine?.getPlatformViewsController()?.setBackNodeControllers(); - } else { - this.inputMethodController.detach(); - } - }); let observer:errorManager.ErrorObserver = { onUnhandledException(errorMsg) { Log.e(TAG, "onUnhandledException, errorMsg:", errorMsg); @@ -120,7 +109,7 @@ export class FlutterAbility extends UIAbility implements Host { onDestroy() { FlutterManager.getInstance().popUIAbility(this); - this.context.eventHub.off(EVENT_BACK_PRESS); + errorManager.off('error', this.errorManagerId); if (this.flutterView != null) { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbilityAndEntryDelegate.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbilityAndEntryDelegate.ets index 480371d807..f9f09d12c4 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbilityAndEntryDelegate.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterAbilityAndEntryDelegate.ets @@ -36,10 +36,12 @@ import FlutterNapi from '../engine/FlutterNapi'; import { FlutterView } from '../../view/FlutterView'; import FlutterManager from './FlutterManager'; import Any from '../../plugin/common/Any'; +import inputMethod from '@ohos.inputMethod'; const TAG = "FlutterAbilityDelegate"; const PLUGINS_RESTORATION_BUNDLE_KEY = "plugins"; const FRAMEWORK_RESTORATION_BUNDLE_KEY = "framework"; +const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS'; /** * 主要职责: @@ -55,7 +57,8 @@ class FlutterAbilityAndEntryDelegate implements ExclusiveAppComponent protected isFlutterEngineFromHostOrCache: boolean = false; private engineGroup?: FlutterEngineGroup; private isHost:boolean = false; - private flutterView?: FlutterView + private flutterView?: FlutterView; + private inputMethodController: inputMethod.InputMethodController = inputMethod.getController(); constructor(host?: Host) { this.host = host; @@ -94,6 +97,14 @@ class FlutterAbilityAndEntryDelegate implements ExclusiveAppComponent this.flutterView.attachToFlutterEngine(this.flutterEngine!!); } this.host?.configureFlutterEngine(this.flutterEngine!!); + this.context.eventHub.on(EVENT_BACK_PRESS, () => { + if (this.flutterView?.getKeyboardHeight() == 0) { + this.flutterEngine?.getNavigationChannel()?.popRoute(); + this.flutterEngine?.getPlatformViewsController()?.setBackNodeControllers(); + } else { + this.inputMethodController.detach(); + } + }); } /** @@ -302,6 +313,7 @@ class FlutterAbilityAndEntryDelegate implements ExclusiveAppComponent } this.isAttached = false; + this.context?.eventHub.off(EVENT_BACK_PRESS); } onLowMemory(): void { -- Gitee From bcf80204d63cf61dbe49de5e3fcc81fbc0113705 Mon Sep 17 00:00:00 2001 From: wuzhiming Date: Fri, 8 Nov 2024 10:09:35 +0800 Subject: [PATCH 100/151] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20patch=20?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wuzhiming --- attachment/repos/swiftshader.patch | 3 ++- attachment/scripts/config.json | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/attachment/repos/swiftshader.patch b/attachment/repos/swiftshader.patch index e1606d8da2..ca2a1fd728 100644 --- a/attachment/repos/swiftshader.patch +++ b/attachment/repos/swiftshader.patch @@ -95,4 +95,5 @@ index 30897f020..a6c3031c2 100644 - pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset); #elif defined(__FreeBSD__) cpuset_t cpuset; - CPU_ZERO(&cpuset); \ No newline at end of file + CPU_ZERO(&cpuset); + \ No newline at end of file diff --git a/attachment/scripts/config.json b/attachment/scripts/config.json index 0e768859f2..62ec1a4f35 100644 --- a/attachment/scripts/config.json +++ b/attachment/scripts/config.json @@ -73,8 +73,8 @@ }, { "name": "swiftshader", - "target": "./src/third_party/swiftshader", + "target": "third_party/swiftshader", "type": "patch", - "file_path": "../../flutter/attachment/repos/swiftshader.patch" + "file_path": "flutter/attachment/repos/swiftshader.patch" } ] -- Gitee From bd9864950dd8dc1b2bb70bf24edc364967d3c0dc Mon Sep 17 00:00:00 2001 From: wuzhiming Date: Fri, 8 Nov 2024 10:38:40 +0800 Subject: [PATCH 101/151] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20patch=20?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wuzhiming --- attachment/repos/swiftshader.patch | 1 - attachment/scripts/config_pre.json | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/attachment/repos/swiftshader.patch b/attachment/repos/swiftshader.patch index ca2a1fd728..4aec111634 100644 --- a/attachment/repos/swiftshader.patch +++ b/attachment/repos/swiftshader.patch @@ -96,4 +96,3 @@ index 30897f020..a6c3031c2 100644 #elif defined(__FreeBSD__) cpuset_t cpuset; CPU_ZERO(&cpuset); - \ No newline at end of file diff --git a/attachment/scripts/config_pre.json b/attachment/scripts/config_pre.json index 0e768859f2..62ec1a4f35 100644 --- a/attachment/scripts/config_pre.json +++ b/attachment/scripts/config_pre.json @@ -73,8 +73,8 @@ }, { "name": "swiftshader", - "target": "./src/third_party/swiftshader", + "target": "third_party/swiftshader", "type": "patch", - "file_path": "../../flutter/attachment/repos/swiftshader.patch" + "file_path": "flutter/attachment/repos/swiftshader.patch" } ] -- Gitee From c11ffcb005c65c89e4eb6d0246dd7a3defb97cfd Mon Sep 17 00:00:00 2001 From: asklie <760956257@qq.com> Date: Fri, 8 Nov 2024 10:59:08 +0800 Subject: [PATCH 102/151] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E8=8E=B7?= =?UTF-8?q?=E5=8F=96content=E4=B8=BAundefined=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: asklie <760956257@qq.com> --- .../systemchannels/TextInputChannel.ets | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets index 99a9d4f39c..23fe07c7d3 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets @@ -448,20 +448,23 @@ class TextInputCallback implements MethodCallHandler { width: 0, height: 0, } + isListenWindow: boolean = false; constructor(handler: TextInputMethodHandler) { this.textInputMethodHandler = handler; - const context = getContext(this) as Context - window.getLastWindow(context, (err: BusinessError, data: window.Window) => { - this.windowPosition = data.getWindowProperties().windowRect as window.Rect; - data.on('windowRectChange', (rect: window.RectChangeOptions) => { - this.windowPosition = rect.rect as window.Rect; - this.setCursorPosition(); - }) - }) - } setCursorPosition() { + if (!this.isListenWindow) { + this.isListenWindow = true; + const context = getContext(this) as Context + window.getLastWindow(context, (err: BusinessError, data: window.Window) => { + this.windowPosition = data.getWindowProperties().windowRect as window.Rect; + data.on('windowRectChange', (rect: window.RectChangeOptions) => { + this.windowPosition = rect.rect as window.Rect; + this.setCursorPosition(); + }) + }) + } const left = (this.windowPosition.left as number) + (this.cursorPosition.left + this.inputPosotion.left) * this.devicePixelRatio; const top = (this.windowPosition.top as number) + (this.cursorPosition.top + this.inputPosotion.top) * this.devicePixelRatio; this.textInputMethodHandler.setCursorSizeAndPosition({ -- Gitee From b30b303934cdc0dc38e37273da14a49fd90b7210 Mon Sep 17 00:00:00 2001 From: hezhengyi Date: Thu, 7 Nov 2024 17:33:35 +0800 Subject: [PATCH 103/151] =?UTF-8?q?=E5=A4=96=E6=8E=A5=E7=BA=B9=E7=90=86?= =?UTF-8?q?=E8=B0=83=E6=95=B4,=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E5=9C=BA=E6=99=AF=E9=BB=91=E5=B1=8F=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hezhengyi --- .../ohos/ohos_external_texture_gl.cpp | 48 +++++++------------ .../platform/ohos/ohos_external_texture_gl.h | 2 - shell/platform/ohos/platform_view_ohos.cpp | 2 + 3 files changed, 18 insertions(+), 34 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 374e63a1d0..58f774a9c7 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -122,6 +122,8 @@ OHOSExternalTextureGL::~OHOSExternalTextureGL() void OHOSExternalTextureGL::Attach() { + FML_DLOG(INFO) << "Attach, texture_name_=" << texture_name_ + << ", Id()=" << Id(); if (state_ != AttachmentState::uninitialized) { FML_LOG(ERROR) << "OHOSExternalTextureGL::Attach, the current status is not uninitialized"; return; @@ -164,16 +166,23 @@ void OHOSExternalTextureGL::Paint(PaintContext& context, const SkSamplingOptions& sampling) { if (state_ == AttachmentState::detached) { - FML_LOG(ERROR) << "OHOSExternalTextureGL::Paint, the current status is detached"; + FML_LOG(ERROR) << "Paint, the current status is detached"; return; } - if (!freeze && texture_update_ && pixelMap_ == nullptr) { - // 多引擎场景(multi_flutters_ohos)需要在这里执行Update + if (state_ == AttachmentState::uninitialized) { + Attach(); + if (pixelMap_ != nullptr) { + // 外接纹理图片场景 + ProducePixelMapToNativeImage(); + new_frame_ready_ = true; + } + } + if (!freeze && new_frame_ready_) { Update(); + new_frame_ready_ = false; } GrGLTextureInfo textureInfo; - if (!freeze && !first_update_ && !isEmulator_ && !new_frame_ready_ && pixelMap_ == nullptr) { setBackground(bounds.width(), bounds.height()); textureInfo = {GL_TEXTURE_EXTERNAL_OES, backGroundTextureName_, GL_RGBA8_OES}; @@ -227,22 +236,16 @@ void OHOSExternalTextureGL::OnGrContextDestroyed() << ", Id()=" << Id(); if (state_ == AttachmentState::attached) { Detach(); - state_ = AttachmentState::detached; + glDeleteTextures(1, &texture_name_); + glDeleteTextures(1, &backGroundTextureName_); } + state_ = AttachmentState::detached; } void OHOSExternalTextureGL::MarkNewFrameAvailable() { FML_DLOG(INFO) << " OHOSExternalTextureGL::MarkNewFrameAvailable"; new_frame_ready_ = true; - texture_update_ = true; - if (texture_name_ == 0) { - Attach(); - } - if (pixelMap_ != nullptr) { // 外接纹理图片场景 - ProducePixelMapToNativeImage(); - } - Update(); } void OHOSExternalTextureGL::OnTextureUnregistered() @@ -266,7 +269,6 @@ void OHOSExternalTextureGL::Update() return; } int32_t ret = OH_NativeImage_UpdateSurfaceImage(nativeImage_); - texture_update_ = false; if (ret != 0) { FML_LOG(ERROR) << "OHOSExternalTextureGL OH_NativeImage_UpdateSurfaceImage err code:" << ret; return; @@ -282,7 +284,6 @@ void OHOSExternalTextureGL::Detach() FML_LOG(ERROR) << "OHOSExternalTextureGL::Detach, the current status is not attached"; return; } - if (nativeImage_ != nullptr) { OH_NativeImage_DetachContext(nativeImage_); OH_NativeImage_UnsetOnFrameAvailableListener(nativeImage_); @@ -303,15 +304,6 @@ void OHOSExternalTextureGL::Detach() OH_NativeWindow_DestroyNativeWindow(backGroundNativeWindow_); backGroundNativeWindow_ = nullptr; } - - if (texture_name_ != 0) { - glDeleteTextures(1, &texture_name_); - texture_name_ = 0; - } - if (backGroundTextureName_ != 0) { - glDeleteTextures(1, &backGroundTextureName_); - backGroundTextureName_ = 0; - } } void OHOSExternalTextureGL::UpdateTransform(OH_NativeImage *image) @@ -487,10 +479,6 @@ void OHOSExternalTextureGL::ProducePixelMapToBackGroundImage() usage |= NATIVEBUFFER_USAGE_CPU_READ | (BUFFER_USAGE_HW_COMPOSER); OH_NativeWindow_NativeWindowHandleOpt(backGroundNativeWindow_, SET_USAGE, usage); - if (backGroundBuffer_ != nullptr) { - OH_NativeWindow_NativeWindowAbortBuffer(backGroundNativeWindow_, backGroundBuffer_); - backGroundBuffer_ = nullptr; - } ret = OH_NativeWindow_NativeWindowRequestBuffer(backGroundNativeWindow_, &backGroundBuffer_, &backGroundFenceFd); if (ret != 0) { FML_LOG(ERROR) @@ -613,10 +601,6 @@ void OHOSExternalTextureGL::ProducePixelMapToNativeImage() usage |= NATIVEBUFFER_USAGE_CPU_READ | (BUFFER_USAGE_HW_COMPOSER); OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_USAGE, usage); - if (buffer_ != nullptr) { - OH_NativeWindow_NativeWindowAbortBuffer(nativeWindow_, buffer_); - buffer_ = nullptr; - } ret = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow_, &buffer_, &fenceFd); if (ret != 0) { FML_LOG(ERROR) << "OHOSExternalTextureGL OH_NativeWindow_NativeWindowRequestBuffer err:" << ret; diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h index 26847c228b..2458ac9c54 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.h +++ b/shell/platform/ohos/ohos_external_texture_gl.h @@ -97,8 +97,6 @@ class OHOSExternalTextureGL : public flutter::Texture { bool new_frame_ready_ = false; - bool texture_update_ = false; - GLuint texture_name_ = 0; GLuint backGroundTextureName_ = 0; diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index 956e8c03a9..f4cfb6ef02 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -439,6 +439,7 @@ void PlatformViewOHOS::RegisterExternalTextureByImage( RegisterTexture(ohos_external_gl); ohos_external_gl->DispatchImage(image); } + MarkTextureFrameAvailable(texture_id); } } @@ -478,6 +479,7 @@ uint64_t PlatformViewOHOS::RegisterExternalTexture(int64_t texture_id) } external_texture_gl_[texture_id] = ohos_external_gl; RegisterTexture(ohos_external_gl); + MarkTextureFrameAvailable(texture_id); } return surface_id; } -- Gitee From 430d82190683eefff08d56cab045788b87902505 Mon Sep 17 00:00:00 2001 From: hezhengyi Date: Sat, 9 Nov 2024 16:35:10 +0800 Subject: [PATCH 104/151] =?UTF-8?q?=E5=A4=96=E6=8E=A5=E7=BA=B9=E7=90=86?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hezhengyi --- shell/platform/ohos/ohos_external_texture_gl.cpp | 7 +++---- shell/platform/ohos/ohos_external_texture_gl.h | 4 ---- shell/platform/ohos/platform_view_ohos.cpp | 3 +-- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 58f774a9c7..785ba786f0 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -92,8 +92,6 @@ OHOSExternalTextureGL::OHOSExternalTextureGL( backGroundNativeWindow_ = nullptr; eglContext_ = EGL_NO_CONTEXT; eglDisplay_ = EGL_NO_DISPLAY; - buffer_ = nullptr; - backGroundBuffer_ = nullptr; pixelMap_ = nullptr; backGroundPixelMap_ = nullptr; lastImage_ = nullptr; @@ -113,8 +111,6 @@ OHOSExternalTextureGL::~OHOSExternalTextureGL() backGroundNativeWindow_ = nullptr; eglContext_ = EGL_NO_CONTEXT; eglDisplay_ = EGL_NO_DISPLAY; - buffer_ = nullptr; - backGroundBuffer_ = nullptr; pixelMap_ = nullptr; backGroundPixelMap_ = nullptr; lastImage_ = nullptr; @@ -407,6 +403,7 @@ void OHOSExternalTextureGL::ProduceColorToBackGroundImage(int32_t width, int32_t usage |= NATIVEBUFFER_USAGE_CPU_READ | (BUFFER_USAGE_HW_COMPOSER); OH_NativeWindow_NativeWindowHandleOpt(backGroundNativeWindow_, SET_USAGE, usage); + OHNativeWindowBuffer *backGroundBuffer_; ret = OH_NativeWindow_NativeWindowRequestBuffer(backGroundNativeWindow_, &backGroundBuffer_, &backGroundFenceFd); if (ret != 0) { FML_LOG(ERROR) << "OHOSExternalTextureGL::setBackground OH_NativeWindow_NativeWindowRequestBuffer err:" << ret; @@ -479,6 +476,7 @@ void OHOSExternalTextureGL::ProducePixelMapToBackGroundImage() usage |= NATIVEBUFFER_USAGE_CPU_READ | (BUFFER_USAGE_HW_COMPOSER); OH_NativeWindow_NativeWindowHandleOpt(backGroundNativeWindow_, SET_USAGE, usage); + OHNativeWindowBuffer *backGroundBuffer_; ret = OH_NativeWindow_NativeWindowRequestBuffer(backGroundNativeWindow_, &backGroundBuffer_, &backGroundFenceFd); if (ret != 0) { FML_LOG(ERROR) @@ -601,6 +599,7 @@ void OHOSExternalTextureGL::ProducePixelMapToNativeImage() usage |= NATIVEBUFFER_USAGE_CPU_READ | (BUFFER_USAGE_HW_COMPOSER); OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_USAGE, usage); + OHNativeWindowBuffer *buffer_; ret = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow_, &buffer_, &fenceFd); if (ret != 0) { FML_LOG(ERROR) << "OHOSExternalTextureGL OH_NativeWindow_NativeWindowRequestBuffer err:" << ret; diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h index 2458ac9c54..fadf5a9cce 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.h +++ b/shell/platform/ohos/ohos_external_texture_gl.h @@ -109,10 +109,6 @@ class OHOSExternalTextureGL : public flutter::Texture { OHNativeWindow *backGroundNativeWindow_; - OHNativeWindowBuffer *buffer_; - - OHNativeWindowBuffer *backGroundBuffer_; - NativePixelMap* backGroundPixelMap_; NativePixelMap* pixelMap_; diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index f4cfb6ef02..adc8d5ec3d 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -439,7 +439,6 @@ void PlatformViewOHOS::RegisterExternalTextureByImage( RegisterTexture(ohos_external_gl); ohos_external_gl->DispatchImage(image); } - MarkTextureFrameAvailable(texture_id); } } @@ -451,6 +450,7 @@ PointerDataDispatcherMaker PlatformViewOHOS::GetDispatcherMaker() { uint64_t PlatformViewOHOS::RegisterExternalTexture(int64_t texture_id) { + FML_DLOG(INFO) << "PlatformViewOHOS::RegisterExternalTexture, texture_id=" << texture_id; uint64_t surface_id = 0; int ret = -1; if (ohos_context_->RenderingApi() == OHOSRenderingAPI::kOpenGLES) { @@ -479,7 +479,6 @@ uint64_t PlatformViewOHOS::RegisterExternalTexture(int64_t texture_id) } external_texture_gl_[texture_id] = ohos_external_gl; RegisterTexture(ohos_external_gl); - MarkTextureFrameAvailable(texture_id); } return surface_id; } -- Gitee From 93cdb21f205382d75f0b82e26422c0bbf66b384c Mon Sep 17 00:00:00 2001 From: HHHxm2 Date: Mon, 11 Nov 2024 15:56:01 +0800 Subject: [PATCH 105/151] Signed-off-by: HHHxm2 flutter page register drag event handler --- .../ohos/flutter_embedding/flutter/index.ets | 2 +- .../ets/embedding/ohos/FlutterManager.ets | 25 ++++++++++ .../main/ets/embedding/ohos/FlutterPage.ets | 48 +++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/index.ets b/shell/platform/ohos/flutter_embedding/flutter/index.ets index 91a7282d72..8e44d57256 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/index.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/index.ets @@ -60,7 +60,7 @@ export { default as FlutterAbilityLaunchConfigs } from './src/main/ets/embedding export { default as FlutterEngineConfigurator } from './src/main/ets/embedding/ohos/FlutterEngineConfigurator'; export { default as FlutterEngineProvider } from './src/main/ets/embedding/ohos/FlutterEngineProvider'; export { default as FlutterEntry } from './src/main/ets/embedding/ohos/FlutterEntry'; -export { default as FlutterManager } from './src/main/ets/embedding/ohos/FlutterManager'; +export { default as FlutterManager, DragDropCallback as DragDropCallback } from './src/main/ets/embedding/ohos/FlutterManager'; export * from './src/main/ets/embedding/ohos/FlutterPage'; export { default as KeyboardManager } from './src/main/ets/embedding/ohos/KeyboardManager'; export { default as OhosTouchProcessor } from './src/main/ets/embedding/ohos/OhosTouchProcessor'; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterManager.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterManager.ets index 0f449572ed..de56a3343e 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterManager.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterManager.ets @@ -18,6 +18,7 @@ import { FlutterView } from '../../view/FlutterView'; import UIAbility from '@ohos.app.ability.UIAbility'; import window from '@ohos.window'; import Log from '../../util/Log'; +import List from '@ohos.util.List'; const TAG = "FlutterManager" @@ -36,6 +37,26 @@ export default class FlutterManager { private uiAbilityList = new Array(); private windowStageList = new Map(); private mFullScreenListener: FullScreenListener = new DefaultFullScreenListener(); + private dragEnterCbs: List = new List(); + private dragMoveCbs: List = new List(); + private dragLeaveCbs: List = new List(); + private dropCbs: List = new List(); + + getDragEnterCbs() { + return this.dragEnterCbs; + } + + getDragMoveCbs() { + return this.dragMoveCbs; + } + + getDragLeaveCbs() { + return this.dragLeaveCbs; + } + + getDropCbs() { + return this.dropCbs; + } pushUIAbility(uiAbility: UIAbility) { this.uiAbilityList.push(uiAbility); @@ -118,6 +139,10 @@ export default class FlutterManager { } } +export interface DragDropCallback { + do(event: DragEvent, extraParams: string): void; +} + export interface FullScreenListener { useFullScreen(): boolean; setUseFullScreen(useFullScreen: boolean, context?: Context | null | undefined): void; diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets index 15af51a2dd..0162cf764e 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets @@ -84,6 +84,30 @@ export struct FlutterPage { this.flutterView?.onKeyEvent(event); return false; }) + .onDragEnter((event: DragEvent, extraParams: string) => { + FlutterManager.getInstance().getDragEnterCbs().forEach(dragEnterCb => { + dragEnterCb.do(event, extraParams); + }); + Log.d(TAG, "onDragEnter"); + }) + .onDragMove((event: DragEvent, extraParams: string) => { + FlutterManager.getInstance().getDragMoveCbs().forEach(dragMoveCb => { + dragMoveCb.do(event, extraParams); + }); + Log.d(TAG, "onDragMove"); + }) + .onDragLeave((event: DragEvent, extraParams: string) => { + FlutterManager.getInstance().getDragLeaveCbs().forEach(dragLeaveCb => { + dragLeaveCb.do(event, extraParams); + }); + Log.d(TAG, "onDragLeave"); + }) + .onDrop((event: DragEvent, extraParams: string) => { + FlutterManager.getInstance().getDropCbs().forEach(dropCb => { + dropCb.do(event, extraParams); + }); + Log.d(TAG, "onDrop"); + }) } @Builder mouseWheelPage() { Stack() { @@ -138,6 +162,30 @@ export struct FlutterPage { this.flutterView?.onKeyEvent(event); return false; }) + .onDragEnter((event: DragEvent, extraParams: string) => { + FlutterManager.getInstance().getDragEnterCbs().forEach(dragEnterCb => { + dragEnterCb.do(event, extraParams); + }); + Log.d(TAG, "onDragEnter"); + }) + .onDragMove((event: DragEvent, extraParams: string) => { + FlutterManager.getInstance().getDragMoveCbs().forEach(dragMoveCb => { + dragMoveCb.do(event, extraParams); + }); + Log.d(TAG, "onDragMove"); + }) + .onDragLeave((event: DragEvent, extraParams: string) => { + FlutterManager.getInstance().getDragLeaveCbs().forEach(dragLeaveCb => { + dragLeaveCb.do(event, extraParams); + }); + Log.d(TAG, "onDragLeave"); + }) + .onDrop((event: DragEvent, extraParams: string) => { + FlutterManager.getInstance().getDropCbs().forEach(dropCb => { + dropCb.do(event, extraParams); + }); + Log.d(TAG, "onDrop"); + }) .gesture( PanGesture(this.panOption) .onActionStart((event: GestureEvent) => { -- Gitee From e63bf0e8c433b86225c87f9441288b9832a721ba Mon Sep 17 00:00:00 2001 From: hezhengyi Date: Mon, 11 Nov 2024 15:11:33 +0800 Subject: [PATCH 106/151] =?UTF-8?q?KeyEvent=E4=BA=8B=E4=BB=B6=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=80=BB=E8=BE=91=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hezhengyi --- shell/platform/ohos/flutter_embedding/.gitignore | 2 +- .../src/main/ets/embedding/ohos/FlutterPage.ets | 14 ++++++++------ ...HandlerForEmulator.ets => KeyEventHandler.ets} | 11 ++--------- .../main/ets/embedding/ohos/KeyboardManager.ets | 15 ++++++++++----- .../flutter/src/main/ets/view/FlutterView.ets | 8 ++++++-- 5 files changed, 27 insertions(+), 23 deletions(-) rename shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/{KeyEventHandlerForEmulator.ets => KeyEventHandler.ets} (96%) diff --git a/shell/platform/ohos/flutter_embedding/.gitignore b/shell/platform/ohos/flutter_embedding/.gitignore index c5c48a55d3..c837164ae8 100644 --- a/shell/platform/ohos/flutter_embedding/.gitignore +++ b/shell/platform/ohos/flutter_embedding/.gitignore @@ -1,5 +1,5 @@ /node_modules -/oh_modules +**/oh_modules /.idea **/build /.hvigor diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets index 15af51a2dd..ddb2fbec75 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterPage.ets @@ -80,9 +80,10 @@ export struct FlutterPage { } }) .onKeyPreIme((event: KeyEvent) => { - Log.d(TAG, "onKeyEvent " + event.type); - this.flutterView?.onKeyEvent(event); - return false; + return this.flutterView?.onKeyPreIme(event) ?? false; + }) + .onKeyEvent((event: KeyEvent) => { + return this.flutterView?.onKeyEvent(event) ?? false; }) } @Builder mouseWheelPage() { @@ -134,9 +135,10 @@ export struct FlutterPage { } }) .onKeyPreIme((event: KeyEvent) => { - Log.d(TAG, "onKeyEvent " + event.type); - this.flutterView?.onKeyEvent(event); - return false; + return this.flutterView?.onKeyPreIme(event) ?? false; + }) + .onKeyEvent((event: KeyEvent) => { + return this.flutterView?.onKeyEvent(event) ?? false; }) .gesture( PanGesture(this.panOption) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyEventHandlerForEmulator.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyEventHandler.ets similarity index 96% rename from shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyEventHandlerForEmulator.ets rename to shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyEventHandler.ets index 34e179d714..58133fd461 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyEventHandlerForEmulator.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyEventHandler.ets @@ -19,9 +19,9 @@ import TextInputPlugin from "../../plugin/editing/TextInputPlugin"; import Log from "../../util/Log"; import { KeyCode } from "@kit.InputKit"; -const TAG = "KeyEventHandlerForEmulator"; +const TAG = "KeyEventHandler"; -export class KeyEventHandlerForEmulator { +export class KeyEventHandler { private textInputPlugin?: TextInputPlugin; private charMap : HashMap = new HashMap(); private shiftMap : HashMap = new HashMap(); @@ -144,18 +144,11 @@ export class KeyEventHandlerForEmulator { } } - isEmulator() : boolean { - return deviceInfo.productModel == 'emulator'; - } - handleKeyEvent(event: KeyEvent) { Log.i(TAG, JSON.stringify({ "name": "handleKeyEvent", "event": event })); - if (!this.isEmulator()) { - return; - } if (event.type == KeyType.Up) { // 处理字符按键相关逻辑 if (this.charMap.hasKey(event.keyCode)) { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyboardManager.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyboardManager.ets index 0951c126fb..21b5c88934 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyboardManager.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/KeyboardManager.ets @@ -15,23 +15,28 @@ import TextInputPlugin from '../../plugin/editing/TextInputPlugin'; import FlutterEngine from '../engine/FlutterEngine'; import KeyEventChannel, { FlutterKeyEvent } from '../engine/systemchannels/KeyEventChannel'; -import { KeyEventHandlerForEmulator } from './KeyEventHandlerForEmulator'; +import { KeyEventHandler } from './KeyEventHandler'; export default class KeyboardManager { private keyEventChannel: KeyEventChannel | null = null - private keyEventHandlerForEmulator: KeyEventHandlerForEmulator; + private keyEventHandler: KeyEventHandler; constructor(engine: FlutterEngine, textInputPlugin: TextInputPlugin) { this.keyEventChannel = new KeyEventChannel(engine.dartExecutor) - this.keyEventHandlerForEmulator = new KeyEventHandlerForEmulator(textInputPlugin); + this.keyEventHandler = new KeyEventHandler(textInputPlugin); } - handleKeyEvent(event: KeyEvent) { + onKeyPreIme(event: KeyEvent) : boolean { this.keyEventChannel?.sendFlutterKeyEvent(new FlutterKeyEvent(event), event.type == KeyType.Up, { onFrameworkResponse: (isEventHandled: boolean): void => { } }) - this.keyEventHandlerForEmulator.handleKeyEvent(event); + return false; + } + + onKeyEvent(event: KeyEvent) : boolean { + this.keyEventHandler.handleKeyEvent(event); + return false; } } \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index aeb9518b6a..853ce08722 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -452,8 +452,12 @@ export class FlutterView { return false; } - onKeyEvent(event: KeyEvent) { - this.keyboardManager?.handleKeyEvent(event) + onKeyPreIme(event: KeyEvent) : boolean { + return this.keyboardManager?.onKeyPreIme(event) ?? false; + } + + onKeyEvent(event: KeyEvent) : boolean { + return this.keyboardManager?.onKeyEvent(event) ?? false; } onMouseWheel(eventType: string, event: PanGestureEvent) { -- Gitee From e4057bd6b77320bd054856cf33c2e66f2073eb01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BA=A6=E7=A9=97?= Date: Mon, 11 Nov 2024 19:38:36 +0800 Subject: [PATCH 107/151] =?UTF-8?q?=E4=BF=AE=E5=A4=8DlocalizationChannel?= =?UTF-8?q?=E7=9A=84sendLocales=E6=96=B9=E6=B3=95=E7=9A=84=E6=96=AD?= =?UTF-8?q?=E8=A8=80=E7=BB=93=E6=9E=9C=E4=B8=BA'zh-Hans-CN'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 麦穗 --- .../ets/test/plugin/localization/LocalizationPlugin.test.ets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/localization/LocalizationPlugin.test.ets b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/localization/LocalizationPlugin.test.ets index b8b5f8f9f0..36d725f79f 100644 --- a/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/localization/LocalizationPlugin.test.ets +++ b/shell/platform/ohos/flutter_embedding/application/src/ohosTest/ets/test/plugin/localization/LocalizationPlugin.test.ets @@ -37,7 +37,7 @@ export default function LocalizationPluginTest() { }); it('test_localeFromString', 0, () => { let localeString = "zh_CN"; - let expectedLocale = new intl.Locale("zh_CN"); + let expectedLocale = new intl.Locale("zh-Hans-CN"); let actualLocale = localizationPlugin.localeFromString(localeString); expect(actualLocale.language).assertEqual(expectedLocale.language); @@ -45,7 +45,7 @@ export default function LocalizationPluginTest() { expect(actualLocale.script).assertEqual(expectedLocale.script); }) it('testSendLocaleToFlutter', 0, () => { - let mockSystemLocale = 'zh-Hans-AL'; + let mockSystemLocale = 'zh-Hans-CN'; (localizationChannel as Any).sendLocales = (locales:Any) => { expect(locales).assertContain(mockSystemLocale); }; -- Gitee From a2ab5b9a6ac83d63a3196f6d73fe5cfed5340bb8 Mon Sep 17 00:00:00 2001 From: HHHxm2 Date: Tue, 12 Nov 2024 20:42:02 +0800 Subject: [PATCH 108/151] drag event callback Signed-off-by: HHHxm2 --- .../ets/embedding/ohos/FlutterManager.ets | 75 ++++++++++++++++--- 1 file changed, 63 insertions(+), 12 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterManager.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterManager.ets index de56a3343e..b3e2f0598c 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterManager.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/FlutterManager.ets @@ -18,6 +18,7 @@ import { FlutterView } from '../../view/FlutterView'; import UIAbility from '@ohos.app.ability.UIAbility'; import window from '@ohos.window'; import Log from '../../util/Log'; +import HashMap from '@ohos.util.HashMap'; import List from '@ohos.util.List'; const TAG = "FlutterManager" @@ -37,25 +38,75 @@ export default class FlutterManager { private uiAbilityList = new Array(); private windowStageList = new Map(); private mFullScreenListener: FullScreenListener = new DefaultFullScreenListener(); - private dragEnterCbs: List = new List(); - private dragMoveCbs: List = new List(); - private dragLeaveCbs: List = new List(); - private dropCbs: List = new List(); - getDragEnterCbs() { - return this.dragEnterCbs; + private dragEnterCbId: number = 1; + private dragMoveCbId: number = 1; + private dragLeaveCbId: number = 1; + private dropCbId: number = 1; + + private dragEnterCbs: HashMap = new HashMap(); + private dragMoveCbs: HashMap = new HashMap(); + private dragLeaveCbs: HashMap = new HashMap(); + private dropCbs: HashMap = new HashMap(); + + private getValuesFromMap(map: HashMap): List { + let list: List = new List(); + map.forEach((value, key) => { + list.add(value); + }); + return list; + } + + getDragEnterCbs(): List { + return this.getValuesFromMap(this.dragEnterCbs); + } + + getDragMoveCbs(): List { + return this.getValuesFromMap(this.dragMoveCbs); + } + + getDragLeaveCbs(): List { + return this.getValuesFromMap(this.dragLeaveCbs); + } + + getDropCbs(): List { + return this.getValuesFromMap(this.dropCbs); + } + + addDragEnterCb(callback: DragDropCallback): number { + this.dragEnterCbs.set(this.dragEnterCbId, callback); + return this.dragEnterCbId++; + } + + addDragMoveCb(callback: DragDropCallback): number { + this.dragMoveCbs.set(this.dragMoveCbId, callback); + return this.dragMoveCbId++; + } + + addDragLeaveCb(callback: DragDropCallback): number { + this.dragLeaveCbs.set(this.dragLeaveCbId, callback); + return this.dragLeaveCbId++; + } + + addDropCb(callback: DragDropCallback): number { + this.dropCbs.set(this.dropCbId, callback); + return this.dropCbId++; + } + + removeDragEnterCb(id: number) { + this.dragEnterCbs.remove(id); } - getDragMoveCbs() { - return this.dragMoveCbs; + removeDragMoveCb(id: number) { + this.dragMoveCbs.remove(id); } - getDragLeaveCbs() { - return this.dragLeaveCbs; + removeDragLeaveCb(id: number) { + this.dragLeaveCbs.remove(id); } - getDropCbs() { - return this.dropCbs; + removeDropCb(id: number) { + this.dropCbs.remove(id); } pushUIAbility(uiAbility: UIAbility) { -- Gitee From 52b369ffc829216b48dd6068bec3d04c7b18885a Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 13 Nov 2024 12:14:50 +0800 Subject: [PATCH 109/151] =?UTF-8?q?fix:=E5=AE=8C=E5=96=84=E6=8C=87?= =?UTF-8?q?=E9=92=88=E7=B1=BB=E5=9E=8B=E5=8F=98=E9=87=8F=E9=94=80=E6=AF=81?= =?UTF-8?q?=E5=90=8E=E8=B5=8B=E5=80=BC=E4=B8=BA=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos/accessibility/ohos_accessibility_bridge.cpp | 9 ++++++++- .../ohos/accessibility/ohos_accessibility_bridge.h | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index e0836cecbb..faa3c40dd8 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -118,6 +118,7 @@ void OhosAccessibilityBridge::updateSemantics( FlutterScrollExecution(node, _elementInfo); OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); + _elementInfo = nullptr; } // 判断是否触发liveRegion活动区,当前节点是否活跃(暂不影响正常功能) @@ -250,6 +251,7 @@ void OhosAccessibilityBridge::FlutterPageUpdate( OH_ArkUI_SendAccessibilityAsyncEvent(provider_, pageUpdateEventInfo, callback); OH_ArkUI_DestoryAccessibilityEventInfo(pageUpdateEventInfo); + pageUpdateEventInfo = nullptr; FML_DLOG(INFO) << "PageStateUpdate is end"; } @@ -287,7 +289,9 @@ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() OH_ArkUI_SendAccessibilityAsyncEvent(provider_, reqFocusEventInfo, callback); OH_ArkUI_DestoryAccessibilityEventInfo(reqFocusEventInfo); + reqFocusEventInfo = nullptr; OH_ArkUI_DestoryAccessibilityElementInfo(elementInfo); + elementInfo = nullptr; } /** @@ -330,6 +334,7 @@ void OhosAccessibilityBridge::Announce(std::unique_ptr& message) OH_ArkUI_SendAccessibilityAsyncEvent(provider_, announceEventInfo, callback); OH_ArkUI_DestoryAccessibilityEventInfo(announceEventInfo); + announceEventInfo = nullptr; return; } @@ -993,7 +998,7 @@ std::vector OhosAccessibilityBridge::GetLevelOrderTraversalTree(int32_t std::sort(currNode.childrenInTraversalOrder.begin(), currNode.childrenInTraversalOrder.end()); - for(auto& childId: currNode.childrenInTraversalOrder) { + for (auto& childId: currNode.childrenInTraversalOrder) { auto childNode = GetFlutterSemanticsNode(childId); semanticsQue.push(childNode); } @@ -1525,7 +1530,9 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( // 7.销毁新创建的elementinfo, eventinfo OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); + _elementInfo = nullptr; OH_ArkUI_DestoryAccessibilityEventInfo(eventInfo); + eventInfo = nullptr; FML_DLOG(INFO) << "OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent is end"; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 1eedd1be56..c8a04b45f6 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -234,7 +234,7 @@ class OhosAccessibilityBridge { int64_t elementId, ArkUI_AccessibilityElementInfo* elementInfoFromList, ArkUI_AccessibilityElementInfoList* elementList); - + std::vector GetLevelOrderTraversalTree(int32_t rootId); flutter::SemanticsNode GetFlutterRootSemanticsNode(); std::string GetNodeComponentType(const flutter::SemanticsNode& node); -- Gitee From af008ef3b2385fcd291d735093ccaf67a04d3475 Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 13 Nov 2024 15:47:52 +0800 Subject: [PATCH 110/151] =?UTF-8?q?feat:=E5=AE=8C=E5=96=84flutter=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E7=B1=BB=E5=9E=8B=E8=8E=B7=E5=8F=96=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?,=E5=AF=B9=E6=8E=A5hypium=E8=87=AA=E5=8A=A8=E5=8C=96=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E6=A1=86=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 19 +++++-- .../accessibility/ohos_accessibility_bridge.h | 54 +++++++++++++++++++ 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index faa3c40dd8..3aac3fcfd7 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -1589,11 +1589,9 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( return "Button"; } if (node.HasFlag(FLAGS_::kIsTextField)) { - // arkui没有textfield,这里直接透传或者传递textinput return "TextField"; } if (node.HasFlag(FLAGS_::kIsMultiline)) { - // arkui没有多行文本textfield,这里直接透传 return "TextArea"; } if (node.HasFlag(FLAGS_::kIsLink)) { @@ -1607,7 +1605,7 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( return "Header"; } if (node.HasFlag(FLAGS_::kIsImage)) { - return "Image"; + return "ImageView"; } if (node.HasFlag(FLAGS_::kHasCheckedState)) { if (node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup)) { @@ -1618,8 +1616,19 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( } } if (node.HasFlag(FLAGS_::kHasToggledState)) { - // arkui没有ToggleSwitch,这里透传为Toggle - return "ToggleSwitch"; + return "Switch"; + } + if (node.HasFlag(FLAGS_::kHasImplicitScrolling)) { + if (node.HasAction(ACTIONS_::kScrollLeft) || + node.HasAction(ACTIONS_::kScrollRight)) { + return "HorizontalScrollView"; + } else { + return "ScrollView"; + } + } + if (node.HasAction(ACTIONS_::kIncrease) || + node.HasAction(ACTIONS_::kDecrease)) { + return "SeekBar"; } if ((!node.label.empty() || !node.tooltip.empty() || !node.hint.empty())) { return "Text"; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index c8a04b45f6..2b0f0fdc3c 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -281,5 +281,59 @@ class OhosAccessibilityBridge { bool Contains(const std::string source, const std::string target); }; +enum class AccessibilityAction : int32_t { + kTap = 1 << 0, + kLongPress = 1 << 1, + kScrollLeft = 1 << 2, + kScrollRight = 1 << 3, + kScrollUp = 1 << 4, + kScrollDown = 1 << 5, + kIncrease = 1 << 6, + kDecrease = 1 << 7, + kShowOnScreen = 1 << 8, + kMoveCursorForwardByCharacter = 1 << 9, + kMoveCursorBackwardByCharacter = 1 << 10, + kSetSelection = 1 << 11, + kCopy = 1 << 12, + kCut = 1 << 13, + kPaste = 1 << 14, + kDidGainAccessibilityFocus = 1 << 15, + kDidLoseAccessibilityFocus = 1 << 16, + kCustomAction = 1 << 17, + kDismiss = 1 << 18, + kMoveCursorForwardByWord = 1 << 19, + kMoveCursorBackwardByWord = 1 << 20, + kSetText = 1 << 21, +}; + +enum class AccessibilityFlags : int32_t { + kHasCheckedState = 1 << 0, + kIsChecked = 1 << 1, + kIsSelected = 1 << 2, + kIsButton = 1 << 3, + kIsTextField = 1 << 4, + kIsFocused = 1 << 5, + kHasEnabledState = 1 << 6, + kIsEnabled = 1 << 7, + kIsInMutuallyExclusiveGroup = 1 << 8, + kIsHeader = 1 << 9, + kIsObscured = 1 << 10, + kScopesRoute = 1 << 11, + kNamesRoute = 1 << 12, + kIsHidden = 1 << 13, + kIsImage = 1 << 14, + kIsLiveRegion = 1 << 15, + kHasToggledState = 1 << 16, + kIsToggled = 1 << 17, + kHasImplicitScrolling = 1 << 18, + kIsMultiline = 1 << 19, + kIsReadOnly = 1 << 20, + kIsFocusable = 1 << 21, + kIsLink = 1 << 22, + kIsSlider = 1 << 23, + kIsKeyboardKey = 1 << 24, + kIsCheckStateMixed = 1 << 25, +}; + } // namespace flutter #endif // OHOS_ACCESSIBILITY_BRIDGE_H -- Gitee From b8c587770250c52b0adc882a5df8d31dff006303 Mon Sep 17 00:00:00 2001 From: hezhengyi Date: Thu, 14 Nov 2024 10:26:01 +0800 Subject: [PATCH 111/151] =?UTF-8?q?=E5=A4=96=E6=8E=A5=E7=BA=B9=E7=90=86?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E5=8E=9F=E7=94=9F=E7=BB=84=E4=BB=B6=E5=9C=BA?= =?UTF-8?q?=E6=99=AF,=E4=BF=AE=E6=94=B9=E6=A8=AA=E7=AB=96=E5=B1=8F?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E6=97=B6=E7=95=8C=E9=9D=A2=E5=8F=98=E5=BD=A2?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hezhengyi --- shell/platform/ohos/ohos_external_texture_gl.cpp | 6 ++++-- shell/platform/ohos/ohos_external_texture_gl.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 785ba786f0..8e789862d3 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -170,12 +170,13 @@ void OHOSExternalTextureGL::Paint(PaintContext& context, if (pixelMap_ != nullptr) { // 外接纹理图片场景 ProducePixelMapToNativeImage(); - new_frame_ready_ = true; + new_frame_count++; } } - if (!freeze && new_frame_ready_) { + if (!freeze && new_frame_count > 0) { Update(); new_frame_ready_ = false; + new_frame_count--; } GrGLTextureInfo textureInfo; @@ -242,6 +243,7 @@ void OHOSExternalTextureGL::MarkNewFrameAvailable() { FML_DLOG(INFO) << " OHOSExternalTextureGL::MarkNewFrameAvailable"; new_frame_ready_ = true; + new_frame_count = 2; } void OHOSExternalTextureGL::OnTextureUnregistered() diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h index fadf5a9cce..4f503caf7c 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.h +++ b/shell/platform/ohos/ohos_external_texture_gl.h @@ -96,6 +96,7 @@ class OHOSExternalTextureGL : public flutter::Texture { AttachmentState state_; bool new_frame_ready_ = false; + int new_frame_count = 0; GLuint texture_name_ = 0; -- Gitee From 99696a072bb371675908a6f8b8b7b10d424a1756 Mon Sep 17 00:00:00 2001 From: hezhengyi Date: Thu, 14 Nov 2024 10:29:31 +0800 Subject: [PATCH 112/151] =?UTF-8?q?=E5=A4=96=E6=8E=A5=E7=BA=B9=E7=90=86,?= =?UTF-8?q?=E7=9F=A9=E9=98=B5=E8=BD=AC=E6=8D=A2=E5=A4=B1=E8=B4=A5=E6=97=B6?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E9=BB=98=E8=AE=A4=E7=9F=A9=E9=98=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hezhengyi --- .../ohos/ohos_external_texture_gl.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 8e789862d3..580d45d84d 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -41,6 +41,8 @@ constexpr const char *EGL_KHR_PLATFORM_WAYLAND = "EGL_KHR_platform_wayland"; constexpr const char *EGL_GET_PLATFORM_DISPLAY_EXT = "eglGetPlatformDisplayEXT"; constexpr uint32_t WHITE_COLOR = 0xFFFFFFFF; +const SkScalar DEFAULT_MATRIX[] = {1, 0, 0, 0, -1, 1, 0, 0, 1}; + static int PixelMapToWindowFormat(PIXEL_FORMAT pixel_format) { switch (pixel_format) { @@ -320,7 +322,23 @@ void OHOSExternalTextureGL::UpdateTransform(OH_NativeImage *image) transform.set9(matrix3); SkMatrix inverted; if (!transform.invert(&inverted)) { - FML_LOG(ERROR) << "OHOSExternalTextureGL Invalid SurfaceTexture transformation matrix"; + FML_LOG(ERROR) << "OHOSExternalTextureGL UpdateTransform matrix error"; + + transform.set9(DEFAULT_MATRIX); + if (!transform.invert(&inverted)) { + FML_LOG(ERROR) << "UpdateTransform matrix error again"; + } + + for (int i = 0; i < 3; i++) { + int num = i * 3; + FML_LOG(ERROR) << " " << matrix3[num] << " " << matrix3[num + 1] << " " + << matrix3[num + 2]; + } + for (int i = 0; i < 4; i++) { + int num = i * 4; + FML_LOG(ERROR) << " " << m[num] << " " << m[num + 1] << " " << m[num + 2] + << " " << m[num + 3]; + } } transform = inverted; } -- Gitee From 5f5c0997168dafcd4158b0b9cad2c0c743ee68b5 Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 14 Nov 2024 16:12:06 +0800 Subject: [PATCH 113/151] =?UTF-8?q?refactor:=E5=A2=9E=E5=8A=A0=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos/accessibility/ohos_accessibility_manager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_manager.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_manager.cpp index d88a5acaf0..e9b1499f70 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_manager.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_manager.cpp @@ -26,11 +26,13 @@ OhosAccessibilityManager::~OhosAccessibilityManager() {} void OhosAccessibilityManager::OnAccessibilityStateChanged( bool ohosAccessibilityEnabled) {} -void OhosAccessibilityManager::SetOhosAccessibilityEnabled(bool isEnabled) { +void OhosAccessibilityManager::SetOhosAccessibilityEnabled(bool isEnabled) +{ this->isOhosAccessibilityEnabled_ = isEnabled; } -bool OhosAccessibilityManager::GetOhosAccessibilityEnabled() { +bool OhosAccessibilityManager::GetOhosAccessibilityEnabled() +{ return this->isOhosAccessibilityEnabled_; } -- Gitee From b94c9b6f64422bd20f8c3b0d3dc5498daec1a75d Mon Sep 17 00:00:00 2001 From: hezhengyi Date: Thu, 14 Nov 2024 19:12:57 +0800 Subject: [PATCH 114/151] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hezhengyi --- .../ohos/ohos_external_texture_gl.cpp | 20 +++++-------------- .../platform/ohos/ohos_external_texture_gl.h | 2 +- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 580d45d84d..b7ffeafb0e 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -42,6 +42,7 @@ constexpr const char *EGL_GET_PLATFORM_DISPLAY_EXT = "eglGetPlatformDisplayEXT"; constexpr uint32_t WHITE_COLOR = 0xFFFFFFFF; const SkScalar DEFAULT_MATRIX[] = {1, 0, 0, 0, -1, 1, 0, 0, 1}; +const int UPDATE_FRAME_COUNT = 2; static int PixelMapToWindowFormat(PIXEL_FORMAT pixel_format) { @@ -172,13 +173,13 @@ void OHOSExternalTextureGL::Paint(PaintContext& context, if (pixelMap_ != nullptr) { // 外接纹理图片场景 ProducePixelMapToNativeImage(); - new_frame_count++; + newFrameCount++; } } - if (!freeze && new_frame_count > 0) { + if (!freeze && newFrameCount > 0) { Update(); new_frame_ready_ = false; - new_frame_count--; + newFrameCount--; } GrGLTextureInfo textureInfo; @@ -245,7 +246,7 @@ void OHOSExternalTextureGL::MarkNewFrameAvailable() { FML_DLOG(INFO) << " OHOSExternalTextureGL::MarkNewFrameAvailable"; new_frame_ready_ = true; - new_frame_count = 2; + newFrameCount = UPDATE_FRAME_COUNT; } void OHOSExternalTextureGL::OnTextureUnregistered() @@ -328,17 +329,6 @@ void OHOSExternalTextureGL::UpdateTransform(OH_NativeImage *image) if (!transform.invert(&inverted)) { FML_LOG(ERROR) << "UpdateTransform matrix error again"; } - - for (int i = 0; i < 3; i++) { - int num = i * 3; - FML_LOG(ERROR) << " " << matrix3[num] << " " << matrix3[num + 1] << " " - << matrix3[num + 2]; - } - for (int i = 0; i < 4; i++) { - int num = i * 4; - FML_LOG(ERROR) << " " << m[num] << " " << m[num + 1] << " " << m[num + 2] - << " " << m[num + 3]; - } } transform = inverted; } diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h index 4f503caf7c..a8b5de6629 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.h +++ b/shell/platform/ohos/ohos_external_texture_gl.h @@ -96,7 +96,7 @@ class OHOSExternalTextureGL : public flutter::Texture { AttachmentState state_; bool new_frame_ready_ = false; - int new_frame_count = 0; + int newFrameCount = 0; GLuint texture_name_ = 0; -- Gitee From 143977cb1483bd2c59ef5d39feb7cc8c60c9e711 Mon Sep 17 00:00:00 2001 From: hezhengyi Date: Thu, 14 Nov 2024 20:26:06 +0800 Subject: [PATCH 115/151] =?UTF-8?q?=E5=A4=96=E6=8E=A5=E7=BA=B9=E7=90=86?= =?UTF-8?q?=E8=B0=83=E6=95=B4glDeleteTextures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hezhengyi --- shell/platform/ohos/ohos_external_texture_gl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index b7ffeafb0e..8c8d58f72a 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -236,8 +236,6 @@ void OHOSExternalTextureGL::OnGrContextDestroyed() << ", Id()=" << Id(); if (state_ == AttachmentState::attached) { Detach(); - glDeleteTextures(1, &texture_name_); - glDeleteTextures(1, &backGroundTextureName_); } state_ = AttachmentState::detached; } @@ -305,6 +303,8 @@ void OHOSExternalTextureGL::Detach() OH_NativeWindow_DestroyNativeWindow(backGroundNativeWindow_); backGroundNativeWindow_ = nullptr; } + glDeleteTextures(1, &texture_name_); + glDeleteTextures(1, &backGroundTextureName_); } void OHOSExternalTextureGL::UpdateTransform(OH_NativeImage *image) -- Gitee From 56fee94b47f2d2fc295f4b6e16dc7272a8a3d6ed Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 15 Nov 2024 12:14:50 +0800 Subject: [PATCH 116/151] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0capi=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E8=B0=83=E7=94=A8=E7=9A=84=E5=AE=89=E5=85=A8=E6=A3=80?= =?UTF-8?q?=E6=9F=A5=E5=8A=9F=E8=83=BD,=E4=BC=98=E5=8C=96=E9=83=A8?= =?UTF-8?q?=E5=88=86=E5=86=85=E5=AD=98=E5=AE=89=E5=85=A8=E5=86=99=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 447 +++++++++++------- .../accessibility/ohos_accessibility_bridge.h | 11 +- 2 files changed, 281 insertions(+), 177 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 3aac3fcfd7..2baf359b2b 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -17,18 +17,28 @@ #include #include #include "flutter/fml/logging.h" +#include "flutter/shell/platform/ohos/ohos_logging.h" #include "flutter/shell/common/platform_view.h" #include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/ohos/ohos_shell_holder.h" #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/core/SkScalar.h" +#define ARKUI_SUCCEED_CODE 0 +#define ARKUI_FAILED_CODE -1 +#define ARKUI_BAD_PARAM_CODE -2 +#define ARKUI_OOM_CODE -3 +#define ARKUI_ACCESSIBILITY_CALL_CHECK(X) \ + do { \ + int32_t ret = X; \ + if (ret != ARKUI_SUCCEED_CODE) { \ + LOGE("Failed arkui a11y function call, error code:%{public}d", ret); \ + } \ + } while (false) \ + namespace flutter { - OhosAccessibilityBridge* OhosAccessibilityBridge::bridgeInstance = nullptr; -OhosAccessibilityBridge::OhosAccessibilityBridge() {} - OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() { if(!bridgeInstance) { @@ -42,6 +52,7 @@ void OhosAccessibilityBridge::DestroyInstance() { bridgeInstance = nullptr; } +OhosAccessibilityBridge::OhosAccessibilityBridge() {} /** * 监听当前ohos平台是否开启无障碍屏幕朗读服务 */ @@ -93,6 +104,10 @@ void OhosAccessibilityBridge::updateSemantics( GetSemanticsNodeDebugInfo(node); GetSemanticsFlagsDebugInfo(node); + // if (!IsNodeVisible(node)) { + // continue; + // } + /** * 构建flutter无障碍语义节点树 * NOTE: 若使用flutterSemanticsTree_.insert({node.id, node})方式 @@ -110,7 +125,7 @@ void OhosAccessibilityBridge::updateSemantics( } // 当滑动节点产生滑动,并执行滑动处理 - if (HasScrolled(node)) { + if (HasScrolled(node) && IsNodeVisible(node)) { ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); @@ -121,11 +136,12 @@ void OhosAccessibilityBridge::updateSemantics( _elementInfo = nullptr; } - // 判断是否触发liveRegion活动区,当前节点是否活跃(暂不影响正常功能) + // 判断是否触发liveRegion活动区,当前节点是否活跃 if (node.HasFlag(FLAGS_::kIsLiveRegion)) { FML_DLOG(INFO) - << "UpdateSemantics -> flutterNode is kIsLiveRegion, node.id=" - << node.id; + << "UpdateSemantics -> LiveRegion, node.id=" << node.id; + FlutterPageUpdate(ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); } } @@ -194,12 +210,16 @@ void OhosAccessibilityBridge::FlutterScrollExecution( if (node.scrollChildren > 0) { // 配置当前滑动组件的子节点总数 int32_t itemCount = node.scrollChildren; - OH_ArkUI_AccessibilityElementInfoSetItemCount(elementInfoFromList, - itemCount); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetItemCount( + elementInfoFromList, itemCount) + ); // 设置当前页面可见的起始滑动index int32_t startItemIndex = node.scrollIndex; - OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, - startItemIndex); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, + startItemIndex) + ); // 计算当前滑动位置页面的可见子滑动节点数量 int visibleChildren = 0; @@ -212,19 +232,22 @@ void OhosAccessibilityBridge::FlutterScrollExecution( } // 当可见滑动子节点数量超过滑动组件总子节点数量 if (node.scrollIndex + visibleChildren > node.scrollChildren) { - FML_DLOG(ERROR) + FML_DLOG(WARNING) << "FlutterScrollExecution -> Scroll index is out of bounds"; } // 当滑动击中子节点数量为0 if (!node.childrenInHitTestOrder.size()) { - FML_DLOG(ERROR) << "FlutterScrollExecution -> Had scrollChildren but no " - "childrenInHitTestOrder"; + FML_DLOG(WARNING) << "FlutterScrollExecution -> Had scrollChildren but no " + "childrenInHitTestOrder"; } // 设置当前页面可见的末尾滑动index int32_t endItemIndex = node.scrollIndex + visibleChildren - 1; - OH_ArkUI_AccessibilityElementInfoSetEndItemIndex(elementInfoFromList, - endItemIndex); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetEndItemIndex(elementInfoFromList, + endItemIndex) + ); + } } @@ -234,26 +257,26 @@ void OhosAccessibilityBridge::FlutterScrollExecution( void OhosAccessibilityBridge::FlutterPageUpdate( ArkUI_AccessibilityEventType eventType) { + if (provider_ == nullptr) { + FML_DLOG(ERROR) << "PageStateUpdate ->" + "AccessibilityProvider = nullptr"; + return; + } ArkUI_AccessibilityEventInfo* pageUpdateEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); - OH_ArkUI_AccessibilityEventSetEventType( - pageUpdateEventInfo, eventType); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetEventType(pageUpdateEventInfo, eventType) + ); auto callback = [](int32_t errorCode) { FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; }; - if (provider_ == nullptr) { - FML_DLOG(ERROR) << "PageStateUpdate ->" - "AccessibilityProvider = nullptr"; - return; - } + OH_ArkUI_SendAccessibilityAsyncEvent(provider_, pageUpdateEventInfo, callback); OH_ArkUI_DestoryAccessibilityEventInfo(pageUpdateEventInfo); pageUpdateEventInfo = nullptr; - - FML_DLOG(INFO) << "PageStateUpdate is end"; } /** @@ -261,31 +284,35 @@ void OhosAccessibilityBridge::FlutterPageUpdate( */ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() { + if (provider_ == nullptr) { + FML_DLOG(ERROR) << "RequestFocusWhenPageUpdate ->" + "AccessibilityProvider = nullptr"; + return; + } ArkUI_AccessibilityEventInfo* reqFocusEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); ArkUI_AccessibilityElementInfo* elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); - OH_ArkUI_AccessibilityEventSetEventType( - reqFocusEventInfo, - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_REQUEST_ACCESSIBILITY_FOCUS); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetEventType( + reqFocusEventInfo, + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_REQUEST_ACCESSIBILITY_FOCUS) + ); int32_t requestFocusId = 0; - OH_ArkUI_AccessibilityEventSetRequestFocusId(reqFocusEventInfo, - requestFocusId); - - OH_ArkUI_AccessibilityEventSetElementInfo(reqFocusEventInfo, elementInfo); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetRequestFocusId(reqFocusEventInfo, + requestFocusId) + ); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetElementInfo(reqFocusEventInfo, elementInfo) + ); auto callback = [](int32_t errorCode) { FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; }; - - if (provider_ == nullptr) { - FML_DLOG(ERROR) << "PageStateUpdate ->" - "AccessibilityProvider = nullptr"; - return; - } OH_ArkUI_SendAccessibilityAsyncEvent(provider_, reqFocusEventInfo, callback); OH_ArkUI_DestoryAccessibilityEventInfo(reqFocusEventInfo); @@ -299,38 +326,31 @@ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() */ void OhosAccessibilityBridge::Announce(std::unique_ptr& message) { + if (provider_ == nullptr) { + FML_DLOG(ERROR) << "announce ->" + "AccessibilityProvider = nullptr"; + return; + } // 创建并设置屏幕朗读事件 ArkUI_AccessibilityEventInfo* announceEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); - int32_t ret1 = OH_ArkUI_AccessibilityEventSetEventType( - announceEventInfo, - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ANNOUNCE_FOR_ACCESSIBILITY); - if (ret1 != 0) { - FML_DLOG(INFO) << "OhosAccessibilityBridge::announce " - "OH_ArkUI_AccessibilityEventSetEventType failed"; - return; - } - int32_t ret2 = OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility( - announceEventInfo, message.get()); - if (ret2 != 0) { - FML_DLOG(INFO) - << "OhosAccessibilityBridge::announce " - "OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility failed"; - return; - } - FML_DLOG(INFO) << ("OhosAccessibilityBridge::announce message: ") + + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetEventType( + announceEventInfo, + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ANNOUNCE_FOR_ACCESSIBILITY) + ); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility( + announceEventInfo, message.get()) + ); + FML_DLOG(INFO) << ("announce -> message: ") << (message.get()); auto callback = [](int32_t errorCode) { FML_DLOG(WARNING) << "announce callback-> errorCode =" << errorCode; }; - - if (provider_ == nullptr) { - FML_DLOG(ERROR) << "announce ->" - "AccessibilityProvider = nullptr"; - return; - } OH_ArkUI_SendAccessibilityAsyncEvent(provider_, announceEventInfo, callback); OH_ArkUI_DestoryAccessibilityEventInfo(announceEventInfo); @@ -368,7 +388,7 @@ flutter::SemanticsNode OhosAccessibilityBridge::GetFlutterSemanticsNode( } else { FML_DLOG(ERROR) << "GetFlutterSemanticsNode flutterSemanticsTree_ = null" << id; - return flutter::SemanticsNode{}; + return {}; } } @@ -401,23 +421,29 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( int32_t right = static_cast(flutterNode.rect.fRight); int32_t bottom = static_cast(flutterNode.rect.fBottom); ArkUI_AccessibleRect rect = {left, top, right, bottom}; - OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfo, &rect); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfo, &rect) + ); // 设置elementinfo的action类型 std::string widget_type = GetNodeComponentType(flutterNode); FlutterSetElementInfoOperationActions(elementInfo, widget_type); // 设置elementid - OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfo, flutterNode.id); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfo, flutterNode.id) + ); // 设置父节点id int32_t parentId = GetParentId(flutterNode.id); if (flutterNode.id == 0) { - OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, -2100000); - FML_DLOG(INFO) << "FlutterTreeToArkuiTree parent.id= " << parentId; + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, ARKUI_ACCESSIBILITY_ROOT_PARENT_ID) + ); } else { - OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, parentId); - FML_DLOG(INFO) << "FlutterTreeToArkuiTree parent.id= " << parentId; + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, parentId) + ); } // 设置孩子节点 @@ -431,29 +457,38 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( << flutterNode.id << " childCount= " << childCount << " childNodeId=" << childNodeIds[i]; } - OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfo, childCount, - childNodeIds); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfo, + childCount, + childNodeIds) + ); // 配置常用属性,force to true for debugging - OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfo, true); - OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfo, true); - OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfo, true); - OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfo, true); - OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfo, true); - + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfo, true)); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfo, true)); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfo, true)); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfo, true)); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfo, true)); + // 设置组件类型 std::string componentTypeName = GetNodeComponentType(flutterNode); - OH_ArkUI_AccessibilityElementInfoSetComponentType( - elementInfo, componentTypeName.c_str()); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetComponentType( + elementInfo, componentTypeName.c_str()) + ); std::string contents = componentTypeName + "_content"; - OH_ArkUI_AccessibilityElementInfoSetContents(elementInfo, contents.c_str()); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetContents(elementInfo, contents.c_str()) + ); // 设置无障碍相关属性 - OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( - elementInfo, flutterNode.label.c_str()); - OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfo, "yes"); - OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfo, false); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( + elementInfo, flutterNode.label.c_str()) + ); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfo, "yes")); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfo, false)); } FML_DLOG(INFO) << "FlutterTreeToArkuiTree is end"; } @@ -463,18 +498,21 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( */ int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) { - int32_t childElementId = static_cast(elementId); if (!parentChildIdVec.size()) { FML_DLOG(INFO) << "OhosAccessibilityBridge::GetParentId parentChildIdMap.size()=0"; - return -2100000; + return ARKUI_ACCESSIBILITY_ROOT_PARENT_ID; + } + if (elementId == -1) { + return ARKUI_ACCESSIBILITY_ROOT_PARENT_ID; } + int32_t childElementId = static_cast(elementId); for (const auto& item : parentChildIdVec) { if (item.second == childElementId) { return item.first; } } - return -2100000; + return RET_ERROR_STATE_CODE; } /** @@ -532,6 +570,10 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( // 获取当前flutter节点的父节点的相对rect int32_t parentId = GetParentId(currNode.id); auto parentNode = GetFlutterSemanticsNode(parentId); + // if (parentNode == ) { + // LOGE("ConvertChildRelativeRectToScreenRect -> GetFlutterSemanticsNode + // parentNode = null, parentId:%{public}d", parentId); + // } auto parentRight = parentNode.rect.fRight; auto parentBottom = parentNode.rect.fBottom; @@ -549,7 +591,10 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( // 真实缩放系数 float realScaleFactor = realParentRight / parentRight * 1.0; - float newLeft, newTop, newRight, newBottom; + float newLeft; + float newTop; + float newRight; + float newBottom; if (_kMScaleX > 1 && _kMScaleY > 1) { // 子节点相对父节点进行变化(缩放、 平移) @@ -563,13 +608,13 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( // 若当前节点的相对坐标与父亲节点的相对坐标值相同,则直接继承坐标值 if (currRight == parentRight && currBottom == parentBottom) { newLeft = realParentLeft; - newTop = realParentTop; - newRight = realParentRight; + newTop = realParentTop; + newRight = realParentRight; newBottom = realParentBottom; } else { // 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 newLeft = (currLeft + _kMTransX) * realScaleFactor + realParentLeft; - newTop = (currTop + _kMTransY) * realScaleFactor + realParentTop; + newTop = (currTop + _kMTransY) * realScaleFactor + realParentTop; newRight = (currLeft + _kMTransX + currRight) * realScaleFactor + realParentLeft; newBottom = @@ -585,8 +630,8 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( << ", " << newRight << ", " << newBottom << ")}"; // 防止滑动场景下绿框坐标超出屏幕范围,进行正则化处理 newLeft = static_cast(newLeft) % static_cast(rootWidth); - newTop = static_cast(newTop) % static_cast(rootHeight); - newRight = static_cast(newRight) % static_cast(rootWidth); + newTop = static_cast(newTop) % static_cast(rootHeight); + newRight = static_cast(newRight) % static_cast(rootWidth); newBottom = static_cast(newBottom) % static_cast(rootHeight); SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); @@ -624,7 +669,11 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( int32_t right = static_cast(flutterNode.rect.fRight); int32_t bottom = static_cast(flutterNode.rect.fBottom); ArkUI_AccessibleRect rect = {left, top, right, bottom}; - OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetScreenRect( + elementInfoFromList, &rect) + ); + // 设置root节点的屏幕绝对坐标rect SetAbsoluteScreenRect(0, left, top, right, bottom); @@ -633,18 +682,29 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); // 根据flutternode信息配置对应的elementinfo - OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, 0); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, 0) + ); + // NOTE: arkui无障碍子系统强制设置root的父节点id = -2100000 (严禁更改) - OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, -2100000); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetParentId( + elementInfoFromList, ARKUI_ACCESSIBILITY_ROOT_PARENT_ID) + ); + // 设置无障碍播报文本 - OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( - elementInfoFromList, flutterNode.label.empty() - ? flutterNode.hint.c_str() - : flutterNode.label.c_str()); - OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, - "yes"); - OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, - false); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( + elementInfoFromList, flutterNode.label.empty() ? flutterNode.hint.c_str() : flutterNode.label.c_str()) + ); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel( + elementInfoFromList, "yes") + ); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup( + elementInfoFromList, false) + ); // 配置child节点信息 int32_t childCount = flutterNode.childrenInTraversalOrder.size(); @@ -657,17 +717,18 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( << "FlutterNodeToElementInfoById -> elementid=0 childCount=" << childCount << " childNodeIds=" << childNodeIds[i]; } - OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, - childCount, childNodeIds); - + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds( + elementInfoFromList, childCount, childNodeIds) + ); + // 配置root节点常用属性 - OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true); - OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true); - OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true); - OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); - OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, - "root"); - OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, flutterNode.label.c_str()); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true)); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true)); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true)); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true)); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root")); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, flutterNode.label.c_str())); } else { //当elementId >= 1时,根据flutter节点信息配置elementinfo无障碍属性 FlutterSetElementInfoProperties(elementInfoFromList, elementId); @@ -737,9 +798,10 @@ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION; actions[9].description = "光标位置设置"; - OH_ArkUI_AccessibilityElementInfoSetOperationActions( - elementInfoFromList, actionTypeNum, actions); - + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetOperationActions( + elementInfoFromList, actionTypeNum, actions) + ); } else if (widget_type == "scrollable") { // if node is a scrollable component int32_t actionTypeNum = 5; @@ -765,9 +827,10 @@ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD; actions[4].description = "向下滑动"; - OH_ArkUI_AccessibilityElementInfoSetOperationActions( - elementInfoFromList, actionTypeNum, actions); - + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetOperationActions( + elementInfoFromList, actionTypeNum, actions) + ); } else { // set common component action types int32_t actionTypeNum = 3; @@ -785,8 +848,10 @@ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; actions[2].description = "点击动作"; - OH_ArkUI_AccessibilityElementInfoSetOperationActions( - elementInfoFromList, actionTypeNum, actions); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetOperationActions( + elementInfoFromList, actionTypeNum, actions) + ); } } @@ -801,8 +866,11 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( GetFlutterSemanticsNode(static_cast(elementId)); // set elementinfo id - OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, - flutterNode.id); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, + flutterNode.id) + ); + // convert relative rect to absolute rect ConvertChildRelativeRectToScreenRect(flutterNode); auto rectPairs = GetAbsoluteScreenRect(flutterNode.id); @@ -812,7 +880,9 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( int32_t right = rectPairs.second.first; int32_t bottom = rectPairs.second.second; ArkUI_AccessibleRect rect = {left, top, right, bottom}; - OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect) + ); FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> node.id= " << flutterNode.id << " SceenRect = (" << left << ", " << top << ", " << right << ", " << bottom << ")"; @@ -834,27 +904,29 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( // set current elementinfo parent id int32_t parentId = GetParentId(elementId); - if (parentId < 0) { - FML_DLOG(ERROR) - << "FlutterNodeToElementInfoById GetParentId is null, assigned to " - << parentId; - OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, parentId); - } else { - OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, parentId); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById GetParentId = " << parentId; - } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, parentId) + ); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById GetParentId = " << parentId; + // set accessibility text for announcing std::string text = flutterNode.label; - OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfoFromList, - text.c_str()); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfoFromList, + text.c_str()) + ); FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetAccessibilityText = " << text; //set contents (same as AccessibilityText) - OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, text.c_str()); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, text.c_str()) + ); std::string hint = flutterNode.hint; - OH_ArkUI_AccessibilityElementInfoSetHintText(elementInfoFromList, - hint.c_str()); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetHintText(elementInfoFromList, + hint.c_str()) + ); // set chidren elementinfo ids int32_t childCount = flutterNode.childrenInTraversalOrder.size(); @@ -867,45 +939,59 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( << " childCount=" << childCount << " childNodeIds=" << childNodeIds[i]; } - OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, - childCount, childNodeIds); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, + childCount, childNodeIds) + ); /** * 根据当前flutter节点的SemanticsFlags特性,配置对应的elmentinfo属性 */ // 判断当前节点是否可点击 if (IsNodeClickable(flutterNode)) { - OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true) + ); FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetClickable -> true"; } // 判断当前节点是否可获焦点 if (IsNodeFocusable(flutterNode)) { - OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true) + ); FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetFocusable -> true"; } // 判断当前节点是否为密码输入框 if (IsNodePassword(flutterNode)) { - OH_ArkUI_AccessibilityElementInfoSetIsPassword(elementInfoFromList, true); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetIsPassword(elementInfoFromList, true) + ); FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetIsPassword -> true"; } // 判断当前节点是否具备checkable状态 (如:checkbox, radio button) if (IsNodeCheckable(flutterNode)) { - OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true) + ); FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetCheckable -> true"; } // 判断当前节点(check box/radio button)是否checked/unchecked if (IsNodeChecked(flutterNode)) { - OH_ArkUI_AccessibilityElementInfoSetChecked(elementInfoFromList, true); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetChecked(elementInfoFromList, true) + ); FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetChecked -> true"; } // 判断当前节点组件是否可显示 if (IsNodeVisible(flutterNode)) { - OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true) + ); FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetVisible -> true"; } @@ -917,13 +1003,17 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( } // 判断当前节点组件是否可滑动 if (IsNodeScrollable(flutterNode)) { - OH_ArkUI_AccessibilityElementInfoSetScrollable(elementInfoFromList, true); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetScrollable(elementInfoFromList, true) + ); FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetScrollable -> true"; } // 判断当前节点组件是否可编辑(文本输入框) if (IsTextField(flutterNode)) { - OH_ArkUI_AccessibilityElementInfoSetEditable(elementInfoFromList, true); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetEditable(elementInfoFromList, true) + ); FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetEditable -> true"; } @@ -934,15 +1024,18 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( } // 判断当前节点组件是否支持长按 if (IsNodeHasLongPress(flutterNode)) { - OH_ArkUI_AccessibilityElementInfoSetLongClickable(elementInfoFromList, - true); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetLongClickable(elementInfoFromList, true) + ); FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetLongClickable -> true"; } // 判断当前节点组件是否enabled if (IsNodeEnabled(flutterNode)) { - OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true) + ); FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetEnabled -> true"; } @@ -953,11 +1046,14 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( << componentTypeName; // flutter节点对应elementinfo所属的组件类型(如:root, button,text等) if (elementId == 0) { - OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, - "root"); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root") + ); } else { - OH_ArkUI_AccessibilityElementInfoSetComponentType( - elementInfoFromList, componentTypeName.c_str()); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, + componentTypeName.c_str()) + ); } FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetComponentType: " << componentTypeName; @@ -969,11 +1065,13 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( * “no”:当前组件不可被无障碍辅助服务所识别 * “no-hide-descendants”:当前组件及其所有子组件不可被无障碍辅助服务所识别 */ - OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, - "yes"); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes"); + ); // 无障碍组,设置为true时表示该组件及其所有子组件为一整个可以选中的组件,无障碍服务将不再关注其子组件内容。默认值:false - OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, - false); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, false); + ); } /** @@ -1060,8 +1158,9 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( } // 开启无障碍导航功能 - accessibilityFeatures_->SetAccessibleNavigation(true, - native_shell_holder_id_); + if(elementId == -1 || elementId == 0) { + accessibilityFeatures_->SetAccessibleNavigation(true, native_shell_holder_id_); + } // 从elementinfolist中获取elementinfo ArkUI_AccessibilityElementInfo* elementInfoFromList = @@ -1486,6 +1585,11 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( int64_t elementId, ArkUI_AccessibilityEventType eventType) { + if (provider_ == nullptr) { + FML_DLOG(ERROR) << "Flutter_SendAccessibilityAsyncEvent " + "AccessibilityProvider = nullptr"; + return; + } // 1.创建eventInfo对象 ArkUI_AccessibilityEventInfo* eventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); @@ -1503,15 +1607,17 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( if (eventType == ArkUI_AccessibilityEventType:: ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED) { - OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused(_elementInfo, - true); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused(_elementInfo, + true) + ); } // 3.设置发送事件,如配置获焦、失焦、点击、滑动事件 - OH_ArkUI_AccessibilityEventSetEventType(eventInfo, eventType); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityEventSetEventType(eventInfo, eventType)); // 4.将eventinfo事件和当前elementinfo进行绑定 - OH_ArkUI_AccessibilityEventSetElementInfo(eventInfo, _elementInfo); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityEventSetElementInfo(eventInfo, _elementInfo)); // 5.调用接口发送到ohos侧 auto callback = [](int32_t errorCode) { @@ -1521,11 +1627,6 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( }; // 6.发送event到OH侧 - if (provider_ == nullptr) { - FML_DLOG(ERROR) << "Flutter_SendAccessibilityAsyncEvent " - "AccessibilityProvider = nullptr"; - return; - } OH_ArkUI_SendAccessibilityAsyncEvent(provider_, eventInfo, callback); // 7.销毁新创建的elementinfo, eventinfo @@ -1605,7 +1706,7 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( return "Header"; } if (node.HasFlag(FLAGS_::kIsImage)) { - return "ImageView"; + return "Image"; } if (node.HasFlag(FLAGS_::kHasCheckedState)) { if (node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup)) { diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 2b0f0fdc3c..17d58b92d1 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -25,15 +25,12 @@ #include "flutter/lib/ui/semantics/semantics_node.h" #include "native_accessibility_channel.h" #include "ohos_accessibility_features.h" + namespace flutter { typedef flutter::SemanticsFlags FLAGS_; typedef flutter::SemanticsAction ACTIONS_; -typedef flutter::SemanticsNode FLUTTER_NODE_; -/** - * flutter和ohos的无障碍服务桥接 - */ struct AbsoluteRect { float left; float top; @@ -59,6 +56,9 @@ struct SemanticsNodeExtent : flutter::SemanticsNode { std::string previousLabel; }; +/** + * flutter和ohos的无障碍服务桥接 + */ class OhosAccessibilityBridge { public: static OhosAccessibilityBridge* GetInstance(); @@ -148,6 +148,9 @@ class OhosAccessibilityBridge { std::shared_ptr nativeAccessibilityChannel_; std::shared_ptr accessibilityFeatures_; + // arkui的root节点的父节点id + static const int32_t ARKUI_ACCESSIBILITY_ROOT_PARENT_ID = -2100000; + static const int32_t RET_ERROR_STATE_CODE = -999; static const int32_t ROOT_NODE_ID = 0; constexpr static const double SCROLL_EXTENT_FOR_INFINITY = 100000.0; constexpr static const double SCROLL_POSITION_CAP_FOR_INFINITY = 70000.0; -- Gitee From 7425a8f6e23de4c4f258c317a8ed7ac71d6d5779 Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 15 Nov 2024 17:46:02 +0800 Subject: [PATCH 117/151] =?UTF-8?q?refactor:=E4=BC=98=E5=8C=96=E9=83=A8?= =?UTF-8?q?=E5=88=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 2baf359b2b..3875792883 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -104,10 +104,6 @@ void OhosAccessibilityBridge::updateSemantics( GetSemanticsNodeDebugInfo(node); GetSemanticsFlagsDebugInfo(node); - // if (!IsNodeVisible(node)) { - // continue; - // } - /** * 构建flutter无障碍语义节点树 * NOTE: 若使用flutterSemanticsTree_.insert({node.id, node})方式 @@ -365,12 +361,12 @@ flutter::SemanticsNode OhosAccessibilityBridge::GetFlutterRootSemanticsNode() if (!flutterSemanticsTree_.size()) { FML_DLOG(ERROR) << "GetFlutterRootSemanticsNode -> flutterSemanticsTree_.size()=0"; - return flutter::SemanticsNode{}; + return {}; } if (flutterSemanticsTree_.find(0) == flutterSemanticsTree_.end()) { FML_DLOG(ERROR) << "GetFlutterRootSemanticsNode -> flutterSemanticsTree_ " "has no keys = 0"; - return flutter::SemanticsNode{}; + return {}; } return flutterSemanticsTree_.at(0); } @@ -570,10 +566,6 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( // 获取当前flutter节点的父节点的相对rect int32_t parentId = GetParentId(currNode.id); auto parentNode = GetFlutterSemanticsNode(parentId); - // if (parentNode == ) { - // LOGE("ConvertChildRelativeRectToScreenRect -> GetFlutterSemanticsNode - // parentNode = null, parentId:%{public}d", parentId); - // } auto parentRight = parentNode.rect.fRight; auto parentBottom = parentNode.rect.fBottom; @@ -621,9 +613,13 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( (currTop + _kMTransY + currBottom) * realScaleFactor + realParentTop; } // 若子节点rect超过父节点则跳过显示(单个屏幕显示不下,滑动再重新显示) - if (newLeft < realParentLeft || newTop < realParentTop || - newRight > realParentRight || newBottom > realParentBottom || - newLeft >= newRight || newTop >= newBottom) { + const bool IS_OVER_SCREEN_AREA = newLeft < realParentLeft || + newTop < realParentTop || + newRight > realParentRight || + newBottom > realParentBottom || + newLeft >= newRight || + newTop >= newBottom; + if (IS_OVER_SCREEN_AREA) { FML_DLOG(ERROR) << "ConvertChildRelativeRectToScreenRect childRect is " "bigger than parentRect -> { nodeId: " << currNode.id << ", (" << newLeft << ", " << newTop @@ -1096,7 +1092,7 @@ std::vector OhosAccessibilityBridge::GetLevelOrderTraversalTree(int32_t std::sort(currNode.childrenInTraversalOrder.begin(), currNode.childrenInTraversalOrder.end()); - for (auto& childId: currNode.childrenInTraversalOrder) { + for (const auto& childId: currNode.childrenInTraversalOrder) { auto childNode = GetFlutterSemanticsNode(childId); semanticsQue.push(childNode); } -- Gitee From 6aa43c75e2319901ccd1b6ba486dd42f47d6bb13 Mon Sep 17 00:00:00 2001 From: keminLuo Date: Tue, 19 Nov 2024 09:59:51 +0800 Subject: [PATCH 118/151] =?UTF-8?q?=E8=A7=A3=E5=86=B3updateViewportMetrics?= =?UTF-8?q?=E9=A2=91=E7=B9=81=E8=B0=83=E7=94=A8=EF=BC=9B=E6=96=B0=E5=A2=9E?= =?UTF-8?q?trace=E8=B7=9F=E8=B8=AA=E4=B8=BB=E7=BA=BF=E7=A8=8B=E5=92=8CUI?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E8=A7=A6=E6=91=B8=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: keminLuo --- fml/platform/ohos/message_loop_ohos.cc | 2 +- .../flutter/src/main/ets/view/FlutterView.ets | 10 ++++--- shell/platform/ohos/ohos_touch_processor.cpp | 8 ++++++ shell/platform/ohos/platform_view_ohos.cpp | 27 +++++++++++++++++++ shell/platform/ohos/platform_view_ohos.h | 10 +++++++ 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/fml/platform/ohos/message_loop_ohos.cc b/fml/platform/ohos/message_loop_ohos.cc index 5e528abe99..c918e9e66c 100644 --- a/fml/platform/ohos/message_loop_ohos.cc +++ b/fml/platform/ohos/message_loop_ohos.cc @@ -33,7 +33,7 @@ void MessageLoopOhos::OnPollCallback(uv_poll_t* handle, int status, int events) { if (status < 0) { - FML_DLOG(ERROR) << "Poll error:" << uv_strerror(status); + FML_LOG(ERROR) << "Poll error:" << uv_strerror(status); return; } diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index 7c88fdec45..26889cc34b 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -158,13 +158,15 @@ export class FlutterView { this.gestureAvoidArea = this.mainWindow?.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM_GESTURE); this.keyboardAvoidArea = this.mainWindow?.getWindowAvoidArea(window.AvoidAreaType.TYPE_KEYBOARD); - //监听系统设置显示大小改变 + // Subscribes to display changes. Example: event that the display size is changed. try { display.on("change", ()=>{ this.displayInfo = display.getDefaultDisplaySync(); - this.viewportMetrics.devicePixelRatio = this.displayInfo?.densityPixels; - Log.i(TAG, "Display on: " + JSON.stringify(this.displayInfo)) - this.updateViewportMetrics() + if (this.viewportMetrics.devicePixelRatio != this.displayInfo?.densityPixels) { + this.viewportMetrics.devicePixelRatio = this.displayInfo?.densityPixels; + Log.i(TAG, "Display on: " + JSON.stringify(this.displayInfo)) + this.updateViewportMetrics() + } }); } catch (e) { Log.e(TAG, "displayInfo error" + JSON.stringify(e)); diff --git a/shell/platform/ohos/ohos_touch_processor.cpp b/shell/platform/ohos/ohos_touch_processor.cpp index 2e0af90819..c5cb4c697d 100644 --- a/shell/platform/ohos/ohos_touch_processor.cpp +++ b/shell/platform/ohos/ohos_touch_processor.cpp @@ -16,6 +16,7 @@ #include "flutter/shell/platform/ohos/ohos_touch_processor.h" #include "flutter/lib/ui/window/pointer_data_packet.h" #include "flutter/shell/platform/ohos/ohos_shell_holder.h" +#include "flutter/fml/trace_event.h" namespace flutter { @@ -151,6 +152,7 @@ void OhosTouchProcessor::HandleTouchEvent( if (touchEvent == nullptr) { return; } + FML_TRACE_EVENT("flutter", "HandleTouchEvent", "timeStamp", touchEvent->timeStamp); const int numTouchPoints = 1; std::unique_ptr packet = std::make_unique(numTouchPoints); PointerData pointerData; @@ -197,6 +199,12 @@ void OhosTouchProcessor::HandleTouchEvent( ohos_shell_holder->GetPlatformView()->DispatchPointerDataPacket( std::move(packet)); + // For DFX + fml::closure task = [timeStampDFX = touchEvent->timeStamp](void){ + FML_TRACE_EVENT("flutter", "HandleTouchEventUI", "timeStamp", touchEvent->timeStamp); + }; + ohos_shell_holder->GetPlatformView()->RunTask(OHOS_THREAD_TYPE::OHOS_THREAD_TYPE_UI, task); + int numPoints = touchEvent->numPoints; float tiltX = 0.0; float tiltY = 0.0; diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index adc8d5ec3d..af274ce75a 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -577,6 +577,33 @@ void PlatformViewOHOS::OnTouchEvent(const std::shared_ptr touchPa return napi_facade_->FlutterViewOnTouchEvent(touchPacketString, size); } +void PlatformViewOHOS::RunTask(OHOS_THREAD_TYPE type, const fml::closure& task) +{ + fml::RefPtr TaskRunnerPtr = nullptr; + switch(type) { + case OHOS_THREAD_TYPE::OHOS_THREAD_TYPE_PLATFORM: + TaskRunnerPtr = task_runners_.GetPlatformTaskRunner(); + break; + case OHOS_THREAD_TYPE::OHOS_THREAD_TYPE_UI: + TaskRunnerPtr = task_runners_.GetUITaskRunner(); + break; + case OHOS_THREAD_TYPE::OHOS_THREAD_TYPE_RASTER: + TaskRunnerPtr = task_runners_.GetRasterTaskRunner(); + break; + case OHOS_THREAD_TYPE::OHOS_THREAD_TYPE_IO: + TaskRunnerPtr = task_runners_.GetIOTaskRunner(); + break; + default: + break; + } + + if (!TaskRunnerPtr) { + return; + } + + fml::TaskRunner::RunNowOrPostTask(TaskRunnerPtr, task); +} + OhosImageFrameData::OhosImageFrameData( PlatformViewOHOS* context, int64_t texture_id) diff --git a/shell/platform/ohos/platform_view_ohos.h b/shell/platform/ohos/platform_view_ohos.h index 14c60e884c..bcf1ffc053 100644 --- a/shell/platform/ohos/platform_view_ohos.h +++ b/shell/platform/ohos/platform_view_ohos.h @@ -38,6 +38,13 @@ namespace flutter { +enum OHOS_THREAD_TYPE_TYPE { + OHOS_THREAD_TYPE_PLATFORM, + OHOS_THREAD_TYPE_UI, + OHOS_THREAD_TYPE_RASTER, + OHOS_THREAD_TYPE_IO, +}; + class OhosSurfaceFactoryImpl : public OhosSurfaceFactory { public: OhosSurfaceFactoryImpl(const std::shared_ptr& context, @@ -128,8 +135,11 @@ class PlatformViewOHOS final : public PlatformView { const override { return platform_message_handler_; } + void OnTouchEvent(std::shared_ptr touchPacketString, int size); + void RunTask(OHOS_THREAD_TYPE type, const fml::closure& task); + private: const std::shared_ptr napi_facade_; std::shared_ptr ohos_context_; -- Gitee From cd38efaa5827926b9e8308ab8a1ee81b387bd033 Mon Sep 17 00:00:00 2001 From: hezhengyi Date: Tue, 19 Nov 2024 16:15:46 +0800 Subject: [PATCH 119/151] =?UTF-8?q?=E9=80=82=E9=85=8DDevEco-Studio=205.0.5?= =?UTF-8?q?.200?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hezhengyi --- attachment/scripts/ohos.py | 2 +- attachment/scripts/ohos_create_flutter_har.py | 67 +------------------ .../flutter_embedding/build-profile.json5 | 5 +- tools/gn | 2 +- 4 files changed, 5 insertions(+), 71 deletions(-) diff --git a/attachment/scripts/ohos.py b/attachment/scripts/ohos.py index 49f44d3865..2d21f7848f 100644 --- a/attachment/scripts/ohos.py +++ b/attachment/scripts/ohos.py @@ -328,7 +328,7 @@ def addParseParam(parser): help='Extra param to src/flutter/tools/gn. Such as: -g "\\--enable-unittests"', ) parser.add_argument( - "--ohos_api_int", type=int, choices=[11, 12], default=12, help="Ohos api int." + "--ohos_api_int", type=int, default=13, help="Ohos api int. Deprecated." ) parser.add_argument( "--har-unstripped", action="store_true", help="Use so.unstripped or not." diff --git a/attachment/scripts/ohos_create_flutter_har.py b/attachment/scripts/ohos_create_flutter_har.py index bf21568bdf..cc481911fe 100644 --- a/attachment/scripts/ohos_create_flutter_har.py +++ b/attachment/scripts/ohos_create_flutter_har.py @@ -24,76 +24,12 @@ import subprocess import sys -HAR_CONFIG_TEMPLATE = """ -{ - "app": { - "signingConfigs": [], - "products": [ - { - "name": "default", - "signingConfig": "default", - "compileSdkVersion": "%s", - "compatibleSdkVersion": "%s", - "runtimeOS": "HarmonyOS", - } - ], - "buildModeSet": [ - { - "name": "debug", - }, - { - "name": "release" - }, - { - "name": "profile" - }, - ] - }, - "modules": [ - { - "name": "flutter", - "srcPath": "./flutter" - } - ] -} -""" - - -HVIGOR_CONFIG = """ -{ - "modelVersion": "5.0.0", - "dependencies": { - } -} -""" - - def runGitCommand(command): result = subprocess.run(command, capture_output=True, text=True, shell=True) if result.returncode != 0: raise Exception(f"Git command failed: {result.stderr}") return result.stdout.strip() -# 更新har的配置文件,指定编译使用的api版本 -def updateConfig(buildDir, apiInt): - apiVersionMap = { - 11: "4.1.0(11)", - 12: "5.0.0(12)", - } - apiStr = apiVersionMap[apiInt] - with open( - os.path.join(buildDir, "build-profile.json5"), "w", encoding="utf-8" - ) as file: - file.write(HAR_CONFIG_TEMPLATE % (apiStr, apiStr)) - - if apiInt != 11: - with open( - os.path.join(buildDir, "hvigor", "hvigor-config.json5"), - "w", - encoding="utf-8", - ) as file: - file.write(HVIGOR_CONFIG) - # 自动更新flutter.har的版本号,把日期加到末尾。如: 1.0.0-20240731 def updateVersion(buildDir): @@ -137,7 +73,6 @@ def runCommand(command, checkCode=True, timeout=None): # 编译har文件,通过hvigorw的命令行参数指定编译类型(debug/release/profile) def buildHar(buildDir, apiInt, buildType): - updateConfig(buildDir, apiInt) updateVersion(buildDir) hvigorwCommand = "hvigorw" if apiInt != 11 else (".%shvigorw" % os.sep) runCommand( @@ -160,7 +95,7 @@ def main(): parser.add_argument("--native_lib", action="append", help="Native code library.") parser.add_argument("--ohos_abi", help="Native code ABI.") parser.add_argument( - "--ohos_api_int", type=int, choices=[11, 12], help="Ohos api int." + "--ohos_api_int", type=int, default=13, help="Ohos api int. Deprecated." ) options = parser.parse_args() # copy source code diff --git a/shell/platform/ohos/flutter_embedding/build-profile.json5 b/shell/platform/ohos/flutter_embedding/build-profile.json5 index 87805d1f43..c4150bb5a3 100755 --- a/shell/platform/ohos/flutter_embedding/build-profile.json5 +++ b/shell/platform/ohos/flutter_embedding/build-profile.json5 @@ -20,9 +20,8 @@ { "name": "default", "signingConfig": "default", - "compileSdkVersion": "5.0.0(12)", "compatibleSdkVersion": "5.0.0(12)", - "runtimeOS": "HarmonyOS", + "runtimeOS": "HarmonyOS" } ], "buildModeSet": [ @@ -34,7 +33,7 @@ }, { "name": "profile" - }, + } ] }, "modules": [ diff --git a/tools/gn b/tools/gn index dab248aff2..ccbb3b75e9 100755 --- a/tools/gn +++ b/tools/gn @@ -763,7 +763,7 @@ def parse_args(args): '--ohos-cpu', type=str, choices=['x64', 'x86', 'arm64', 'arm'] ) parser.add_argument( - '--ohos-api-int', type=int, choices=[11, 12], default=11 + '--ohos-api-int', type=int, default=13 ) parser.add_argument( '--fuchsia-cpu', type=str, choices=['x64', 'arm64'], default='x64' -- Gitee From 15b6d509142632ce8bd8a209ce0ab0900a6c9333 Mon Sep 17 00:00:00 2001 From: zjxi Date: Tue, 19 Nov 2024 17:10:59 +0800 Subject: [PATCH 120/151] =?UTF-8?q?refactor:=E4=BF=AE=E6=94=B9=E4=BB=A3?= =?UTF-8?q?=E7=A0=81review=E6=84=8F=E8=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos/accessibility/ohos_accessibility_features.cpp | 7 +++++-- .../ohos/accessibility/ohos_accessibility_manager.h | 5 +++-- .../flutter/src/main/ets/embedding/engine/FlutterNapi.ets | 1 - 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp index f82bc0bbb8..9f4c878508 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_features.cpp @@ -18,7 +18,11 @@ namespace flutter { -OhosAccessibilityFeatures::OhosAccessibilityFeatures() {}; +OhosAccessibilityFeatures::OhosAccessibilityFeatures() +{ + nativeAccessibilityChannel_ = std::make_shared(); +}; + OhosAccessibilityFeatures::~OhosAccessibilityFeatures() {}; /** @@ -67,7 +71,6 @@ void OhosAccessibilityFeatures::SetBoldText(double fontWeightScale, */ void OhosAccessibilityFeatures::SendAccessibilityFlags( int64_t shell_holder_id) { - nativeAccessibilityChannel_ = std::make_shared(); nativeAccessibilityChannel_->SetAccessibilityFeatures(shell_holder_id, accessibilityFeatureFlags); FML_DLOG(INFO) << "SendAccessibilityFlags -> accessibilityFeatureFlags = " << accessibilityFeatureFlags; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_manager.h b/shell/platform/ohos/accessibility/ohos_accessibility_manager.h index 3e37c59e0e..e3c873fe8c 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_manager.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_manager.h @@ -25,13 +25,14 @@ class OhosAccessibilityManager { OhosAccessibilityManager(); ~OhosAccessibilityManager(); - bool isOhosAccessibilityEnabled_; - void OnAccessibilityStateChanged(bool ohosAccessibilityEnabled); bool GetOhosAccessibilityEnabled(); void SetOhosAccessibilityEnabled(bool isEnabled); + + private: + bool isOhosAccessibilityEnabled_; }; } // namespace flutter diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index 72df4d5b04..e36a566682 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -347,7 +347,6 @@ export default class FlutterNapi { setAccessibilityFeatures(accessibilityFeatureFlags: number, responseId: number): void { if (this.isAttached()) { - // this.nativeSetAccessibilityFeatures(accessibilityFeatureFlags, responseId); flutter.nativeSetAccessibilityFeatures(accessibilityFeatureFlags, responseId); } else { Log.w( -- Gitee From 9508d58c9946d12a98f0e0d8af161cc74551b18e Mon Sep 17 00:00:00 2001 From: keminLuo Date: Tue, 19 Nov 2024 22:05:38 +0800 Subject: [PATCH 121/151] =?UTF-8?q?=E8=A7=A3=E5=86=B3updateViewportMetrics?= =?UTF-8?q?=E9=A2=91=E7=B9=81=E8=B0=83=E7=94=A8=EF=BC=9B=E6=96=B0=E5=A2=9E?= =?UTF-8?q?trace=E8=B7=9F=E8=B8=AA=E4=B8=BB=E7=BA=BF=E7=A8=8B=E5=92=8CUI?= =?UTF-8?q?=20=E7=BA=BF=E7=A8=8B=E8=A7=A6=E6=91=B8=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: keminLuo --- shell/platform/ohos/ohos_touch_processor.cpp | 14 ++++-- shell/platform/ohos/ohos_touch_processor.h | 51 +++++++++++--------- shell/platform/ohos/platform_view_ohos.cpp | 2 +- shell/platform/ohos/platform_view_ohos.h | 2 +- 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/shell/platform/ohos/ohos_touch_processor.cpp b/shell/platform/ohos/ohos_touch_processor.cpp index c5cb4c697d..73ace2d742 100644 --- a/shell/platform/ohos/ohos_touch_processor.cpp +++ b/shell/platform/ohos/ohos_touch_processor.cpp @@ -14,6 +14,7 @@ */ #include "flutter/shell/platform/ohos/ohos_touch_processor.h" + #include "flutter/lib/ui/window/pointer_data_packet.h" #include "flutter/shell/platform/ohos/ohos_shell_holder.h" #include "flutter/fml/trace_event.h" @@ -183,7 +184,6 @@ void OhosTouchProcessor::HandleTouchEvent( pointerData.change == PointerData::Change::kMove) { pointerData.buttons = kPointerButtonTouchContact; } - } else if (pointerData.kind == PointerData::DeviceKind::kMouse) { } pointerData.pan_x = 0.0; pointerData.pan_y = 0.0; @@ -200,11 +200,19 @@ void OhosTouchProcessor::HandleTouchEvent( std::move(packet)); // For DFX - fml::closure task = [timeStampDFX = touchEvent->timeStamp](void){ + fml::closure task = [timeStampDFX = touchEvent->timeStamp](void) { FML_TRACE_EVENT("flutter", "HandleTouchEventUI", "timeStamp", touchEvent->timeStamp); }; ohos_shell_holder->GetPlatformView()->RunTask(OHOS_THREAD_TYPE::OHOS_THREAD_TYPE_UI, task); + PlatformViewOnTouchEvent(shell_holderID, toolType, component, touchEvent); +} + +void OhosTouchProcessor::PlatformViewOnTouchEvent(int64_t shellHolderID, + OH_NativeXComponent_TouchPointToolType toolType, + OH_NativeXComponent* component, + OH_NativeXComponent_TouchEvent* touchEvent) +{ int numPoints = touchEvent->numPoints; float tiltX = 0.0; float tiltY = 0.0; @@ -219,8 +227,8 @@ void OhosTouchProcessor::HandleTouchEvent( std::shared_ptr touchPacketString = packagePacketData(std::move(touchPacket)); int size = CHANGES_POINTER_MEMBER + PER_POINTER_MEMBER * numPoints + TOUCH_EVENT_ADDITIONAL_ATTRIBUTES; + auto ohos_shell_holder = reinterpret_cast(shellHolderID); ohos_shell_holder->GetPlatformView()->OnTouchEvent(touchPacketString, size); - return; } void OhosTouchProcessor::HandleMouseEvent( diff --git a/shell/platform/ohos/ohos_touch_processor.h b/shell/platform/ohos/ohos_touch_processor.h index 1f59bd16a9..892bd67293 100644 --- a/shell/platform/ohos/ohos_touch_processor.h +++ b/shell/platform/ohos/ohos_touch_processor.h @@ -24,7 +24,7 @@ namespace flutter { class OhosTouchProcessor { - public: +public: typedef struct { OH_NativeXComponent_TouchEvent* touchEventInput; OH_NativeXComponent_TouchPointToolType toolTypeInput; @@ -32,32 +32,35 @@ class OhosTouchProcessor { float tiltY; } TouchPacket; - public: - void HandleTouchEvent(int64_t shell_holderID, - OH_NativeXComponent* component, - OH_NativeXComponent_TouchEvent* touchEvent); - void HandleMouseEvent(int64_t shell_holderID, - OH_NativeXComponent* component, - OH_NativeXComponent_MouseEvent mouseEvent, - double offsetY); - void HandleVirtualTouchEvent(int64_t shell_holderID, - OH_NativeXComponent* component, - OH_NativeXComponent_TouchEvent* touchEvent); - flutter::PointerData::Change getPointerChangeForAction(int maskedAction); - flutter::PointerData::DeviceKind getPointerDeviceTypeForToolType( - int toolType); - flutter::PointerData::Change getPointerChangeForMouseAction( - OH_NativeXComponent_MouseEventAction mouseAction); - PointerButtonMouse getPointerButtonFromMouse( - OH_NativeXComponent_MouseEventButton mouseButton); +public: + void HandleTouchEvent(int64_t shell_holderID, + OH_NativeXComponent* component, + OH_NativeXComponent_TouchEvent* touchEvent); + void HandleMouseEvent(int64_t shell_holderID, + OH_NativeXComponent* component, + OH_NativeXComponent_MouseEvent mouseEvent, + double offsetY); + void HandleVirtualTouchEvent(int64_t shell_holderID, + OH_NativeXComponent* component, + OH_NativeXComponent_TouchEvent* touchEvent); + flutter::PointerData::Change getPointerChangeForAction(int maskedAction); + flutter::PointerData::DeviceKind getPointerDeviceTypeForToolType( + int toolType); + flutter::PointerData::Change getPointerChangeForMouseAction( + OH_NativeXComponent_MouseEventAction mouseAction); + PointerButtonMouse getPointerButtonFromMouse( + OH_NativeXComponent_MouseEventButton mouseButton); - private: - std::shared_ptr packagePacketData(std::unique_ptr touchPacket); +public: + OH_NativeXComponent_TouchPointToolType touchType_; - public: - OH_NativeXComponent_TouchPointToolType touchType_; +private: + std::shared_ptr packagePacketData(std::unique_ptr touchPacket); - private: + void PlatformViewOnTouchEvent(int64_t shellHolderID, + OH_NativeXComponent_TouchPointToolType toolType, + OH_NativeXComponent* component, + OH_NativeXComponent_TouchEvent* touchEvent); }; } // namespace flutter #endif // XComponent_OhosTouchProcessor_H \ No newline at end of file diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index af274ce75a..f2aa040bc2 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -580,7 +580,7 @@ void PlatformViewOHOS::OnTouchEvent(const std::shared_ptr touchPa void PlatformViewOHOS::RunTask(OHOS_THREAD_TYPE type, const fml::closure& task) { fml::RefPtr TaskRunnerPtr = nullptr; - switch(type) { + switch (type) { case OHOS_THREAD_TYPE::OHOS_THREAD_TYPE_PLATFORM: TaskRunnerPtr = task_runners_.GetPlatformTaskRunner(); break; diff --git a/shell/platform/ohos/platform_view_ohos.h b/shell/platform/ohos/platform_view_ohos.h index bcf1ffc053..0d46543c51 100644 --- a/shell/platform/ohos/platform_view_ohos.h +++ b/shell/platform/ohos/platform_view_ohos.h @@ -38,7 +38,7 @@ namespace flutter { -enum OHOS_THREAD_TYPE_TYPE { +enum class OHOS_THREAD_TYPE { OHOS_THREAD_TYPE_PLATFORM, OHOS_THREAD_TYPE_UI, OHOS_THREAD_TYPE_RASTER, -- Gitee From 82e87bcc4fcfb778a43a7d3b32691af6a1a7bb67 Mon Sep 17 00:00:00 2001 From: keminLuo Date: Wed, 20 Nov 2024 09:56:45 +0800 Subject: [PATCH 122/151] =?UTF-8?q?=E8=AF=AD=E6=B3=95=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: keminLuo --- shell/platform/ohos/ohos_touch_processor.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/shell/platform/ohos/ohos_touch_processor.cpp b/shell/platform/ohos/ohos_touch_processor.cpp index 73ace2d742..32d2ed1ef8 100644 --- a/shell/platform/ohos/ohos_touch_processor.cpp +++ b/shell/platform/ohos/ohos_touch_processor.cpp @@ -201,17 +201,18 @@ void OhosTouchProcessor::HandleTouchEvent( // For DFX fml::closure task = [timeStampDFX = touchEvent->timeStamp](void) { - FML_TRACE_EVENT("flutter", "HandleTouchEventUI", "timeStamp", touchEvent->timeStamp); + FML_TRACE_EVENT("flutter", "HandleTouchEventUI", "timeStamp", timeStampDFX); }; ohos_shell_holder->GetPlatformView()->RunTask(OHOS_THREAD_TYPE::OHOS_THREAD_TYPE_UI, task); PlatformViewOnTouchEvent(shell_holderID, toolType, component, touchEvent); } -void OhosTouchProcessor::PlatformViewOnTouchEvent(int64_t shellHolderID, - OH_NativeXComponent_TouchPointToolType toolType, - OH_NativeXComponent* component, - OH_NativeXComponent_TouchEvent* touchEvent) +void OhosTouchProcessor::PlatformViewOnTouchEvent( + int64_t shellHolderID, + OH_NativeXComponent_TouchPointToolType toolType, + OH_NativeXComponent* component, + OH_NativeXComponent_TouchEvent* touchEvent) { int numPoints = touchEvent->numPoints; float tiltX = 0.0; -- Gitee From a5c29baac45cbfa9b20a7c989a57f86821d195bb Mon Sep 17 00:00:00 2001 From: huangxiaoyao <976125628@qq.com> Date: Wed, 20 Nov 2024 14:56:59 +0800 Subject: [PATCH 123/151] =?UTF-8?q?=E8=A1=A5=E5=85=85COMMITTERS=E5=92=8CRE?= =?UTF-8?q?ADME.OpenSource?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huangxiaoyao <976125628@qq.com> --- COMMITTERS.md | 8 ++++++++ README.OpenSource | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 COMMITTERS.md diff --git a/COMMITTERS.md b/COMMITTERS.md new file mode 100644 index 0000000000..c6fed253df --- /dev/null +++ b/COMMITTERS.md @@ -0,0 +1,8 @@ +## Committers列表 + +### 以下是此项目的committer人员 +不区分先后顺序 + +- [zjzhu](https://gitee.com/appproject) +- [aibin](https://gitee.com/binai) +- [lihui](https://gitee.com/lihui868) \ No newline at end of file diff --git a/README.OpenSource b/README.OpenSource index d0011eeaca..f67241e17a 100644 --- a/README.OpenSource +++ b/README.OpenSource @@ -1,7 +1,7 @@ [ { "Name": "engine", - "License": "BSD 3-Clause License", + "License": "BSD-3-Clause License", "License File": "LICENSE", "Version Number": "3.7.12", "Owner": "aibin@openvalley.net", -- Gitee From 43d353a375bfc893821b67fe4355465ad8fc877b Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 21 Nov 2024 11:00:13 +0800 Subject: [PATCH 124/151] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0api=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=88=A4=E6=96=AD=EF=BC=8C=E9=80=89=E6=8B=A9=E6=80=A7?= =?UTF-8?q?=E8=A7=84=E9=81=BF=E6=97=A0=E9=9A=9C=E7=A2=8D=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- shell/platform/ohos/BUILD.gn | 1 + .../ohos_accessibility_bridge.cpp | 82 ++++++++++--------- .../accessibility/ohos_accessibility_bridge.h | 12 ++- .../platform/ohos/ohos_xcomponent_adapter.cpp | 42 +++++----- shell/platform/ohos/ohos_xcomponent_adapter.h | 3 + 5 files changed, 73 insertions(+), 67 deletions(-) diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn index bf768e8775..4eec7abe9d 100644 --- a/shell/platform/ohos/BUILD.gn +++ b/shell/platform/ohos/BUILD.gn @@ -249,6 +249,7 @@ shared_library("flutter_shell_native") { ldflags += ["-lace_napi.z"] ldflags += ["-lace_ndk.z"] ldflags += ["-lhilog_ndk.z"] + ldflags += ["-ldeviceinfo_ndk.z"] ldflags += ["-luv"] ldflags += ["-lrawfile.z"] ldflags += ["-lEGL"] diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 3875792883..2d07986520 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -24,15 +24,16 @@ #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/core/SkScalar.h" +#define OHOS_API_VERSION 13 #define ARKUI_SUCCEED_CODE 0 #define ARKUI_FAILED_CODE -1 #define ARKUI_BAD_PARAM_CODE -2 #define ARKUI_OOM_CODE -3 #define ARKUI_ACCESSIBILITY_CALL_CHECK(X) \ do { \ - int32_t ret = X; \ - if (ret != ARKUI_SUCCEED_CODE) { \ - LOGE("Failed arkui a11y function call, error code:%{public}d", ret); \ + int32_t RET = X; \ + if (RET != ARKUI_SUCCEED_CODE) { \ + LOGE("Failed arkui a11y function call, error code:%{public}d", RET); \ } \ } while (false) \ @@ -106,15 +107,15 @@ void OhosAccessibilityBridge::updateSemantics( /** * 构建flutter无障碍语义节点树 - * NOTE: 若使用flutterSemanticsTree_.insert({node.id, node})方式 + * NOTE: 若使用g_flutterSemanticsTree.insert({node.id, node})方式 * 来添加新增的语义节点会导致已有key值自动忽略,不会更新原有key对应的value */ - flutterSemanticsTree_[node.id] = node; + g_flutterSemanticsTree[node.id] = node; // 获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 int32_t childNodeCount = node.childrenInTraversalOrder.size(); for (int32_t i = 0; i < childNodeCount; i++) { - parentChildIdVec.emplace_back( + g_parentChildIdVec.emplace_back( std::make_pair(node.id, node.childrenInTraversalOrder[i])); FML_DLOG(INFO) << "UpdateSemantics parentChildIdMap -> (" << node.id << ", " << node.childrenInTraversalOrder[i] << ")"; @@ -145,16 +146,16 @@ void OhosAccessibilityBridge::updateSemantics( for (const auto& item : actions) { const flutter::CustomAccessibilityAction action = item.second; GetCustomActionDebugInfo(action); - actions_mp_[action.id] = action; + g_actions_mp[action.id] = action; } // 打印flutter语义树的不同节点的属性信息 - for (const auto& item : flutterSemanticsTree_) { - FML_DLOG(INFO) << "flutterSemanticsTree_ -> {" << item.first << ", " + for (const auto& item : g_flutterSemanticsTree) { + FML_DLOG(INFO) << "g_flutterSemanticsTree -> {" << item.first << ", " << item.second.id << "}"; } - for (const auto& item : parentChildIdVec) { - FML_DLOG(INFO) << "parentChildIdVec -> (" << item.first << ", " + for (const auto& item : g_parentChildIdVec) { + FML_DLOG(INFO) << "g_parentChildIdVec -> (" << item.first << ", " << item.second << ")"; } @@ -163,6 +164,7 @@ void OhosAccessibilityBridge::updateSemantics( for (const auto& item: levelOrderTraversalTree) { FML_DLOG(INFO) << "LevelOrderTraversalTree: { " << item << " }"; } + FML_DLOG(INFO) << "=== UpdateSemantics is end ==="; } @@ -358,17 +360,17 @@ void OhosAccessibilityBridge::Announce(std::unique_ptr& message) //获取根节点 flutter::SemanticsNode OhosAccessibilityBridge::GetFlutterRootSemanticsNode() { - if (!flutterSemanticsTree_.size()) { + if (!g_flutterSemanticsTree.size()) { FML_DLOG(ERROR) - << "GetFlutterRootSemanticsNode -> flutterSemanticsTree_.size()=0"; + << "GetFlutterRootSemanticsNode -> g_flutterSemanticsTree.size()=0"; return {}; } - if (flutterSemanticsTree_.find(0) == flutterSemanticsTree_.end()) { - FML_DLOG(ERROR) << "GetFlutterRootSemanticsNode -> flutterSemanticsTree_ " + if (g_flutterSemanticsTree.find(0) == g_flutterSemanticsTree.end()) { + FML_DLOG(ERROR) << "GetFlutterRootSemanticsNode -> g_flutterSemanticsTree " "has no keys = 0"; return {}; } - return flutterSemanticsTree_.at(0); + return g_flutterSemanticsTree.at(0); } /** @@ -378,12 +380,12 @@ flutter::SemanticsNode OhosAccessibilityBridge::GetFlutterSemanticsNode( int32_t id) { flutter::SemanticsNode node; - if (flutterSemanticsTree_.count(id) > 0) { - return flutterSemanticsTree_.at(id); + if (g_flutterSemanticsTree.count(id) > 0) { + return g_flutterSemanticsTree.at(id); FML_DLOG(INFO) << "GetFlutterSemanticsNode get node.id=" << id; } else { FML_DLOG(ERROR) - << "GetFlutterSemanticsNode flutterSemanticsTree_ = null" << id; + << "GetFlutterSemanticsNode g_flutterSemanticsTree = null" << id; return {}; } } @@ -394,13 +396,13 @@ flutter::SemanticsNode OhosAccessibilityBridge::GetFlutterSemanticsNode( void OhosAccessibilityBridge::FlutterTreeToArkuiTree( ArkUI_AccessibilityElementInfoList* elementInfoList) { - if (flutterSemanticsTree_.size() == 0) { + if (g_flutterSemanticsTree.size() == 0) { FML_DLOG(ERROR) << "OhosAccessibilityBridge::FlutterTreeToArkuiTree " - "flutterSemanticsTree_.size() = 0"; + "g_flutterSemanticsTree.size() = 0"; return; } // 将flutter语义节点树传递给arkui的无障碍elementinfo - for (const auto& item : flutterSemanticsTree_) { + for (const auto& item : g_flutterSemanticsTree) { flutter::SemanticsNode flutterNode = item.second; // 创建elementinfo,系统自动加入到elementinfolist @@ -494,7 +496,7 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( */ int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) { - if (!parentChildIdVec.size()) { + if (!g_parentChildIdVec.size()) { FML_DLOG(INFO) << "OhosAccessibilityBridge::GetParentId parentChildIdMap.size()=0"; return ARKUI_ACCESSIBILITY_ROOT_PARENT_ID; @@ -503,7 +505,7 @@ int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) return ARKUI_ACCESSIBILITY_ROOT_PARENT_ID; } int32_t childElementId = static_cast(elementId); - for (const auto& item : parentChildIdVec) { + for (const auto& item : g_parentChildIdVec) { if (item.second == childElementId) { return item.first; } @@ -520,7 +522,7 @@ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, float right, float bottom) { - screenRectMap_[flutterNodeId] = + g_screenRectMap[flutterNodeId] = std::make_pair(std::make_pair(left, top), std::make_pair(right, bottom)); FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId << ", <" << left << ", " << top << ", " << right << ", " @@ -530,8 +532,8 @@ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, std::pair, std::pair> OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) { - if (!screenRectMap_.empty() && screenRectMap_.count(flutterNodeId) > 0) { - return screenRectMap_.at(flutterNodeId); + if (!g_screenRectMap.empty() && g_screenRectMap.count(flutterNodeId) > 0) { + return g_screenRectMap.at(flutterNodeId); } else { FML_DLOG(ERROR) << "GetAbsoluteScreenRect -> flutterNodeId=" << flutterNodeId << " is not found !"; @@ -1143,9 +1145,9 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( << elementId << " mode=" << mode << " requestId=" << requestId << " elementList= " << elementList; - if (flutterSemanticsTree_.size() == 0) { + if (g_flutterSemanticsTree.size() == 0) { FML_DLOG(INFO) - << "FindAccessibilityNodeInfosById flutterSemanticsTree_ is null"; + << "FindAccessibilityNodeInfosById g_flutterSemanticsTree is null"; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } if (elementList == nullptr) { @@ -1897,20 +1899,20 @@ void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) void OhosAccessibilityBridge::removeSemanticsNode( flutter::SemanticsNode nodeToBeRemoved) { - if (!flutterSemanticsTree_.size()) { + if (!g_flutterSemanticsTree.size()) { FML_DLOG(ERROR) << "OhosAccessibilityBridge::removeSemanticsNode -> " - "flutterSemanticsTree_.szie()=0"; + "g_flutterSemanticsTree.szie()=0"; return; } - if (flutterSemanticsTree_.find(nodeToBeRemoved.id) == - flutterSemanticsTree_.end()) { + if (g_flutterSemanticsTree.find(nodeToBeRemoved.id) == + g_flutterSemanticsTree.end()) { FML_DLOG(INFO) << "Attempted to remove a node that is not in the tree."; } int32_t nodeToBeRemovedParentId = GetParentId(nodeToBeRemoved.id); - for (auto it = parentChildIdVec.begin(); it != parentChildIdVec.end(); it++) { + for (auto it = g_parentChildIdVec.begin(); it != g_parentChildIdVec.end(); it++) { if (it->first == nodeToBeRemovedParentId && it->second == nodeToBeRemoved.id) { - parentChildIdVec.erase(it); + g_parentChildIdVec.erase(it); } } if (nodeToBeRemoved.platformViewId != -1) { @@ -1923,11 +1925,11 @@ void OhosAccessibilityBridge::removeSemanticsNode( */ void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() { - flutterSemanticsTree_.clear(); - parentChildIdVec.clear(); - screenRectMap_.clear(); - actions_mp_.clear(); - flutterNavigationVec_.clear(); + g_flutterSemanticsTree.clear(); + g_parentChildIdVec.clear(); + g_screenRectMap.clear(); + g_actions_mp.clear(); + g_flutterNavigationVec.clear(); } /** diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 17d58b92d1..def86d8701 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -25,9 +25,7 @@ #include "flutter/lib/ui/semantics/semantics_node.h" #include "native_accessibility_channel.h" #include "ohos_accessibility_features.h" - namespace flutter { - typedef flutter::SemanticsFlags FLAGS_; typedef flutter::SemanticsAction ACTIONS_; @@ -159,14 +157,14 @@ class OhosAccessibilityBridge { flutter::SemanticsNode lastInputFocusedNode; flutter::SemanticsNode accessibilityFocusedNode; - std::vector> parentChildIdVec; - std::map flutterSemanticsTree_; + std::vector> g_parentChildIdVec; + std::map g_flutterSemanticsTree; std::unordered_map< int32_t, std::pair, std::pair>> - screenRectMap_; - std::unordered_map actions_mp_; - std::vector flutterNavigationVec_; + g_screenRectMap; + std::unordered_map g_actions_mp; + std::vector g_flutterNavigationVec; const std::map ArkUI_ACTION_TYPE_MAP_ = { diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp index f0b4ef47eb..2ade6dd389 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.cpp +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -21,7 +21,6 @@ namespace flutter { - bool g_isMouseLeftActive = false; double g_scrollDistance = 0.0; double g_resizeRate = 0.8; @@ -377,27 +376,30 @@ void XComponentBase::SetNativeXComponent(OH_NativeXComponent* nativeXComponent){ OH_NativeXComponent_RegisterCallback(nativeXComponent_, &callback_); OH_NativeXComponent_RegisterMouseEventCallback(nativeXComponent_, &mouseCallback_); - BindAccessibilityProviderCallback(); - ArkUI_AccessibilityProvider* accessibilityProvider = nullptr; - int32_t ret1 = OH_NativeXComponent_GetNativeAccessibilityProvider( - nativeXComponent_, &accessibilityProvider); - if (ret1 != 0) { - LOGE("OH_NativeXComponent_GetNativeAccessibilityProvider is failed"); - return; - } - int32_t ret2 = OH_ArkUI_AccessibilityProviderRegisterCallback( - accessibilityProvider, &accessibilityProviderCallback_); - if (ret2 != 0) { - LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is failed"); - return; - } - LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is %{public}d", ret2); + if (OH_GetSdkApiVersion() >= 13) { + LOGD("api version: %{public}d", OH_GetSdkApiVersion()); + BindAccessibilityProviderCallback(); + ArkUI_AccessibilityProvider* accessibilityProvider = nullptr; + int32_t ret1 = OH_NativeXComponent_GetNativeAccessibilityProvider( + nativeXComponent_, &accessibilityProvider); + if (ret1 != 0) { + LOGE("OH_NativeXComponent_GetNativeAccessibilityProvider is failed"); + return; + } + int32_t ret2 = OH_ArkUI_AccessibilityProviderRegisterCallback( + accessibilityProvider, &accessibilityProviderCallback_); + if (ret2 != 0) { + LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is failed"); + return; + } + LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is %{public}d", ret2); - //将ArkUI_AccessibilityProvider传到无障碍bridge类 - auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); - ohosAccessibilityBridge->provider_ = accessibilityProvider; + //将ArkUI_AccessibilityProvider传到无障碍bridge类 + auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge->provider_ = accessibilityProvider; - LOGI("XComponentBase::SetNativeXComponent OH_ArkUI_AccessibilityProviderRegisterCallback is succeed"); + LOGI("XComponentBase::SetNativeXComponent OH_ArkUI_AccessibilityProviderRegisterCallback is succeed"); + } } } diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.h b/shell/platform/ohos/ohos_xcomponent_adapter.h index d5accff83a..61a181395a 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.h +++ b/shell/platform/ohos/ohos_xcomponent_adapter.h @@ -15,6 +15,7 @@ #ifndef OHOS_XCOMPONENT_ADAPTER_H #define OHOS_XCOMPONENT_ADAPTER_H +#include #include #include #include @@ -24,6 +25,7 @@ #include "napi_common.h" #include #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" + namespace flutter { class XComponentBase @@ -52,6 +54,7 @@ public: OH_NativeXComponent_Callback callback_; OH_NativeXComponent_MouseEvent_Callback mouseCallback_; ArkUI_AccessibilityProviderCallbacks accessibilityProviderCallback_; + std::string id_; std::string shellholderId_; bool isEngineAttached_; -- Gitee From aafca990921646aac1ae413ee8a46d32ebad3cdd Mon Sep 17 00:00:00 2001 From: wwyang <137208408@qq.com> Date: Thu, 21 Nov 2024 15:31:51 +0800 Subject: [PATCH 125/151] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=A4=96=E6=8E=A5?= =?UTF-8?q?=E7=BA=B9=E7=90=86=E5=86=85=E5=AD=98=E6=B3=84=E9=9C=B2=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wwyang <137208408@qq.com> --- .../ohos/EmbeddingNodeController.ets | 40 ++++++++++++++----- .../platform/PlatformViewsController.ets | 36 ++++++++++++----- .../ohos/ohos_external_texture_gl.cpp | 19 ++++++++- .../platform/ohos/ohos_external_texture_gl.h | 2 + 4 files changed, 74 insertions(+), 23 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/EmbeddingNodeController.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/EmbeddingNodeController.ets index a06563f14f..b41df1b44d 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/EmbeddingNodeController.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/ohos/EmbeddingNodeController.ets @@ -30,7 +30,8 @@ declare class nodeControllerParams { const TAG = 'EmbeddingNodeController' export class EmbeddingNodeController extends NodeController { - private rootNode: BuilderNode<[Params]> | undefined | null = null; + private rootNode : FrameNode | null = null; + private builderNode : BuilderNode<[Params]> | undefined | null = null; private wrappedBuilder: WrappedBuilder<[Params]> | null = null; private platformView: PlatformView | undefined = undefined; private embedId : string = ""; @@ -51,24 +52,25 @@ export class EmbeddingNodeController extends NodeController { this.direction = direction; } - makeNode(uiContext: UIContext): FrameNode | null{ - this.rootNode = new BuilderNode(uiContext, { surfaceId: this.surfaceId, type: this.renderType}); + makeNode(uiContext: UIContext): FrameNode | null { + this.rootNode = new FrameNode(uiContext); + this.builderNode = new BuilderNode(uiContext, { surfaceId: this.surfaceId, type: this.renderType }); if (this.wrappedBuilder) { - this.rootNode.build(this.wrappedBuilder, {direction: this.direction, platformView: this.platformView}); + this.builderNode.build(this.wrappedBuilder, { direction: this.direction, platformView: this.platformView }); } - return this.rootNode.getFrameNode(); + return this.builderNode.getFrameNode(); } - setBuilderNode(rootNode: BuilderNode | null): void{ - this.rootNode = rootNode; + setBuilderNode(builderNode: BuilderNode | null): void { + this.builderNode = builderNode; } - getBuilderNode(): BuilderNode<[Params]> | undefined | null{ - return this.rootNode; + getBuilderNode(): BuilderNode<[Params]> | undefined | null { + return this.builderNode; } updateNode(arg: Object): void { - this.rootNode?.update(arg); + this.builderNode?.update(arg); } getEmbedId() : string { return this.embedId; @@ -82,6 +84,22 @@ export class EmbeddingNodeController extends NodeController { } } + disposeFrameNode() { + if (this.rootNode !== null && this.builderNode !== null) { + this.rootNode.removeChild(this.builderNode?.getFrameNode()); + this.builderNode?.dispose(); + + this.rootNode.dispose(); + } + } + + removeBuilderNode() { + const rootRenderNode = this.rootNode!.getRenderNode(); + if (rootRenderNode !== null && this.builderNode !== null && this.builderNode?.getFrameNode() !== null) { + rootRenderNode.removeChild(this.builderNode!.getFrameNode()!.getRenderNode()); + } + } + postEvent(event: TouchEvent | undefined, isPx: boolean = false): boolean { if (event == undefined) { return false; @@ -117,6 +135,6 @@ export class EmbeddingNodeController extends NodeController { } } - return this.rootNode?.postTouchEvent(event) as boolean + return this.builderNode?.postTouchEvent(event) as boolean } } \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/PlatformViewsController.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/PlatformViewsController.ets index 5c88466752..5c929c8418 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/PlatformViewsController.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/plugin/platform/PlatformViewsController.ets @@ -142,21 +142,23 @@ export default class PlatformViewsController implements PlatformViewsAccessibili this.textureRegistry!.unregisterTexture(textureId); } - try { - platformView.dispose(); - } catch (err) { - Log.e(TAG, "Disposing platform view threw an exception", err); - } - let viewWrapper: PlatformViewWrapper | null = this.viewWrappers.get(viewId) || null; if (viewWrapper != null) { - this.viewIdWithNodeController.get(viewId)?.setDestroy(true) + this.viewIdWithNodeController.get(viewId)?.removeBuilderNode() + this.viewIdWithNodeController.get(viewId)?.disposeFrameNode() + this.viewIdWithNodeController.delete(viewId); if (this.flutterView) { let index = this.flutterView.getDVModel().children.indexOf(viewWrapper.getDvModel()!); this.flutterView.getDVModel().children.splice(index, 1); } this.viewWrappers.delete(viewId); } + + try { + platformView.dispose(); + } catch (err) { + Log.e(TAG, "Disposing platform view threw an exception", err); + } } setParams: (params: DVModelParameters, key: string, element: Any ) => void = (params: DVModelParameters, key: string, element: Any): void => { @@ -177,7 +179,7 @@ export default class PlatformViewsController implements PlatformViewsAccessibili let viewWrapper = this.viewWrappers.get(request.viewId) let params: DVModelParameters | undefined = viewWrapper?.getDvModel()!.params - + this.setParams(params!, "width", physicalWidth); this.setParams(params!, "height", physicalHeight); @@ -480,9 +482,21 @@ export default class PlatformViewsController implements PlatformViewsAccessibili return; } } - + public render(surfaceId: number, platformView: PlatformView, width: number, height: number, left: number, top: number) { + + let wrapper = this.viewWrappers.get(surfaceId); + if (wrapper != null) { + let params: DVModelParameters | undefined = wrapper?.getDvModel()!.params + + this.setParams(params!, "width", width); + this.setParams(params!, "height", height); + this.setParams(params!, "left", left); + this.setParams(params!, "top", top); + return; + } + this.flutterView!.setSurfaceId(surfaceId.toString()); let wrappedBuilder: WrappedBuilder<[Params]> = platformView.getView(); this.flutterView?.setWrappedBuilder(wrappedBuilder); @@ -491,8 +505,7 @@ export default class PlatformViewsController implements PlatformViewsAccessibili let nodeController = new EmbeddingNodeController(); nodeController.setRenderOption(platformView, surfaceId.toString(), NodeRenderType.RENDER_TYPE_TEXTURE, Direction.Auto); - - this.nodeControllers.push(nodeController); + this.viewIdWithNodeController.set(surfaceId, nodeController); let dvModel = createDVModelFromJson(new DVModelJson("NodeContainer", [], @@ -510,5 +523,6 @@ export default class PlatformViewsController implements PlatformViewsAccessibili viewWrapper.addDvModel(dvModel); this.viewWrappers.set(surfaceId, viewWrapper); this.flutterView?.getDVModel().children.push(viewWrapper.getDvModel()); + this.platformViews.set(surfaceId, platformView!); } } \ No newline at end of file diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 8c8d58f72a..abc97658ee 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -44,6 +44,8 @@ constexpr uint32_t WHITE_COLOR = 0xFFFFFFFF; const SkScalar DEFAULT_MATRIX[] = {1, 0, 0, 0, -1, 1, 0, 0, 1}; const int UPDATE_FRAME_COUNT = 2; +std::map infoMap; + static int PixelMapToWindowFormat(PIXEL_FORMAT pixel_format) { switch (pixel_format) { @@ -159,6 +161,18 @@ void OHOSExternalTextureGL::Attach() } } +GrGLTextureInfo OHOSExternalTextureGL::GetGrGLTextureInfo() +{ + GrGLTextureInfo textureInfo; + if (infoMap.find(backGroundTextureName_) != infoMap.end()) { + textureInfo = infoMap[backGroundTextureName_]; + } else { + textureInfo = {GL_TEXTURE_EXTERNAL_OES, backGroundTextureName_, GL_RGBA8_OES}; + } + infoMap[backGroundTextureName_] = textureInfo; + return textureInfo; +} + void OHOSExternalTextureGL::Paint(PaintContext& context, const SkRect& bounds, bool freeze, @@ -185,7 +199,7 @@ void OHOSExternalTextureGL::Paint(PaintContext& context, GrGLTextureInfo textureInfo; if (!freeze && !first_update_ && !isEmulator_ && !new_frame_ready_ && pixelMap_ == nullptr) { setBackground(bounds.width(), bounds.height()); - textureInfo = {GL_TEXTURE_EXTERNAL_OES, backGroundTextureName_, GL_RGBA8_OES}; + textureInfo = GetGrGLTextureInfo(); } else { textureInfo = {GL_TEXTURE_EXTERNAL_OES, texture_name_, GL_RGBA8_OES}; } @@ -305,6 +319,9 @@ void OHOSExternalTextureGL::Detach() } glDeleteTextures(1, &texture_name_); glDeleteTextures(1, &backGroundTextureName_); + if (backGroundTextureName_ != 0) { + infoMap.erase(backGroundTextureName_); + } } void OHOSExternalTextureGL::UpdateTransform(OH_NativeImage *image) diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h index a8b5de6629..0fb8dec9f1 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.h +++ b/shell/platform/ohos/ohos_external_texture_gl.h @@ -64,6 +64,8 @@ class OHOSExternalTextureGL : public flutter::Texture { void setBackground(int32_t width, int32_t height); + GrGLTextureInfo GetGrGLTextureInfo(); + void setTextureBufferSize(int32_t width, int32_t height); void DispatchPixelMap(NativePixelMap* pixelMap); -- Gitee From f2356ee677f67038dfb55ca5b6581579776c95d2 Mon Sep 17 00:00:00 2001 From: liujiake Date: Thu, 21 Nov 2024 22:00:06 +0800 Subject: [PATCH 126/151] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=A4=96=E6=8E=A5?= =?UTF-8?q?=E7=BA=B9=E7=90=86=E7=94=9F=E5=91=BD=E5=91=A8=E6=9C=9F=E5=A4=84?= =?UTF-8?q?=E7=90=86=E6=B5=81=E7=A8=8B=EF=BC=8C=E8=A7=A3=E5=86=B3=E8=A7=86?= =?UTF-8?q?=E9=A2=91=E6=92=AD=E8=B7=B3=E8=BD=AC=E8=BF=94=E5=9B=9E=E5=90=8E?= =?UTF-8?q?=E9=BB=91=E5=B1=8F=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- .../ohos/ohos_external_texture_gl.cpp | 61 ++++++++++++-- .../platform/ohos/ohos_external_texture_gl.h | 22 +++++- shell/platform/ohos/platform_view_ohos.cpp | 79 +------------------ shell/platform/ohos/platform_view_ohos.h | 14 ---- 4 files changed, 78 insertions(+), 98 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 8c8d58f72a..6dd6962627 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -42,7 +42,7 @@ constexpr const char *EGL_GET_PLATFORM_DISPLAY_EXT = "eglGetPlatformDisplayEXT"; constexpr uint32_t WHITE_COLOR = 0xFFFFFFFF; const SkScalar DEFAULT_MATRIX[] = {1, 0, 0, 0, -1, 1, 0, 0, 1}; -const int UPDATE_FRAME_COUNT = 2; +const int UPDATE_FRAME_COUNT = 1; static int PixelMapToWindowFormat(PIXEL_FORMAT pixel_format) { @@ -83,8 +83,10 @@ static bool IsPixelMapYUVFormat(PIXEL_FORMAT format) OHOSExternalTextureGL::OHOSExternalTextureGL( int64_t id, - const std::shared_ptr& ohos_surface) + const std::shared_ptr& ohos_surface, + PlatformView::Delegate& delegate) : Texture(id), + delegate_(delegate), ohos_surface_(std::move(ohos_surface)), transform(SkMatrix::I()) { @@ -99,6 +101,7 @@ OHOSExternalTextureGL::OHOSExternalTextureGL( backGroundPixelMap_ = nullptr; lastImage_ = nullptr; isEmulator_ = OhosMain::IsEmulator(); + frameData_ = nullptr; } OHOSExternalTextureGL::~OHOSExternalTextureGL() @@ -119,6 +122,20 @@ OHOSExternalTextureGL::~OHOSExternalTextureGL() lastImage_ = nullptr; } +void OnNativeImageFrameAvailable(void *data) +{ + auto frameData = reinterpret_cast(data); + if (frameData == nullptr) { + FML_DLOG(ERROR) << "OnNativeImageFrameAvailable, frameData is null."; + return; + } + if (!frameData->t) { + FML_DLOG(ERROR) << "OnNativeImageFrameAvailable, frameData value is not valid."; + return; + } + frameData->t->delegate_.OnPlatformViewMarkTextureFrameAvailable(frameData->texture_id_); +} + void OHOSExternalTextureGL::Attach() { FML_DLOG(INFO) << "Attach, texture_name_=" << texture_name_ @@ -153,6 +170,20 @@ void OHOSExternalTextureGL::Attach() if (ret != 0) { FML_LOG(ERROR) << "OHOSExternalTextureGL OH_NativeImage_AttachContext err code:" << ret; } + + if (frameData_ == nullptr) { + frameData_ = new OhosImageFrameData(this, Id()); + } + OH_OnFrameAvailableListener listener; + listener.context = frameData_; + listener.onFrameAvailable = OnNativeImageFrameAvailable; + ret = OH_NativeImage_SetOnFrameAvailableListener(nativeImage_, listener); + if (ret != 0) { + FML_DLOG(ERROR) + << "Error with OH_NativeImage_SetOnFrameAvailableListener"; + return; + } + state_ = AttachmentState::attached; } else { FML_LOG(ERROR) << "ResourceContextMakeCurrent failed"; @@ -174,10 +205,10 @@ void OHOSExternalTextureGL::Paint(PaintContext& context, // 外接纹理图片场景 ProducePixelMapToNativeImage(); newFrameCount++; + Update(); } } if (!freeze && newFrameCount > 0) { - Update(); new_frame_ready_ = false; newFrameCount--; } @@ -226,7 +257,9 @@ void OHOSExternalTextureGL::OnGrContextCreated() FML_DLOG(INFO) << " OHOSExternalTextureGL::OnGrContextCreated" << ", texture_name_=" << texture_name_ << ", Id()=" << Id(); - state_ = AttachmentState::uninitialized; + if (state_ == AttachmentState::attached) { + delegate_.OnPlatformViewMarkTextureFrameAvailable(Id()); + } } void OHOSExternalTextureGL::OnGrContextDestroyed() @@ -234,10 +267,6 @@ void OHOSExternalTextureGL::OnGrContextDestroyed() FML_DLOG(INFO) << " OHOSExternalTextureGL::OnGrContextDestroyed" << ", texture_name_=" << texture_name_ << ", Id()=" << Id(); - if (state_ == AttachmentState::attached) { - Detach(); - } - state_ = AttachmentState::detached; } void OHOSExternalTextureGL::MarkNewFrameAvailable() @@ -245,6 +274,9 @@ void OHOSExternalTextureGL::MarkNewFrameAvailable() FML_DLOG(INFO) << " OHOSExternalTextureGL::MarkNewFrameAvailable"; new_frame_ready_ = true; newFrameCount = UPDATE_FRAME_COUNT; + if (state_ == AttachmentState::attached) { + Update(); + } } void OHOSExternalTextureGL::OnTextureUnregistered() @@ -289,6 +321,10 @@ void OHOSExternalTextureGL::Detach() OH_NativeImage_Destroy(&nativeImage_); nativeImage_ = nullptr; } + if (frameData_ != nullptr) { + delete (OhosImageFrameData *)frameData_; + frameData_ = nullptr; + } if (nativeWindow_ != nullptr) { OH_NativeWindow_DestroyNativeWindow(nativeWindow_); nativeWindow_ = nullptr; @@ -677,4 +713,13 @@ void OHOSExternalTextureGL::DispatchBackGroundPixelMap(NativePixelMap* pixelMap) } } +OhosImageFrameData::OhosImageFrameData( + OHOSExternalTextureGL *t, + int64_t texture_id + ) + : t(t), + texture_id_(texture_id) {} + +OhosImageFrameData::~OhosImageFrameData() = default; + } // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h index a8b5de6629..b8da68b753 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.h +++ b/shell/platform/ohos/ohos_external_texture_gl.h @@ -31,6 +31,7 @@ #include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" #include "flutter/shell/platform/ohos/ohos_surface_gl_skia.h" #include "flutter/shell/platform/ohos/surface/ohos_surface.h" +#include "flutter/shell/common/platform_view.h" // maybe now unused namespace flutter { @@ -38,13 +39,19 @@ namespace flutter { class OHOSExternalTextureGL : public flutter::Texture { public: explicit OHOSExternalTextureGL(int64_t id, const std::shared_ptr& ohos_surface); + explicit OHOSExternalTextureGL(int64_t id, const std::shared_ptr& ohos_surface, + PlatformView::Delegate& delegate); ~OHOSExternalTextureGL() override; + PlatformView::Delegate& delegate_; + OH_NativeImage *nativeImage_; OH_NativeImage *backGroundNativeImage_; + void *frameData_; + bool first_update_ = false; void Paint(PaintContext& context, @@ -96,7 +103,8 @@ class OHOSExternalTextureGL : public flutter::Texture { AttachmentState state_; bool new_frame_ready_ = false; - int newFrameCount = 0; + + std::atomic newFrameCount = 0; GLuint texture_name_ = 0; @@ -129,5 +137,17 @@ class OHOSExternalTextureGL : public flutter::Texture { FML_DISALLOW_COPY_AND_ASSIGN(OHOSExternalTextureGL); }; + +class OhosImageFrameData { + public: + OhosImageFrameData(OHOSExternalTextureGL *t, int64_t texture_id); + + ~OhosImageFrameData(); + + OHOSExternalTextureGL *t; + + int64_t texture_id_; +}; + } // namespace flutter #endif \ No newline at end of file diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index 4285b3d8fd..041ace656a 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -117,17 +117,6 @@ PlatformViewOHOS::PlatformViewOHOS( PlatformViewOHOS::~PlatformViewOHOS() { FML_LOG(INFO) << "PlatformViewOHOS::~PlatformViewOHOS"; - for (std::map::iterator it = contextDatas_.begin(); - it != contextDatas_.end(); ++it) { - if (it->second != nullptr) { - OhosImageFrameData* data = - reinterpret_cast(it->second); - delete data; - data = nullptr; - it->second = nullptr; - } - } - contextDatas_.clear(); } void PlatformViewOHOS::NotifyCreate( @@ -435,7 +424,7 @@ void PlatformViewOHOS::RegisterExternalTextureByImage(int64_t texture_id, iter->second->DispatchImage(image); } else { std::shared_ptr ohos_external_gl = - std::make_shared(texture_id, ohos_surface_); + std::make_shared(texture_id, ohos_surface_, delegate_); external_texture_gl_[texture_id] = ohos_external_gl; RegisterTexture(ohos_external_gl); ohos_external_gl->DispatchImage(image); @@ -456,25 +445,13 @@ uint64_t PlatformViewOHOS::RegisterExternalTexture(int64_t texture_id) int ret = -1; if (ohos_context_->RenderingApi() == OHOSRenderingAPI::kOpenGLES) { std::shared_ptr ohos_external_gl = - std::make_shared(texture_id, ohos_surface_); + std::make_shared(texture_id, ohos_surface_, delegate_); ohos_external_gl->nativeImage_ = OH_NativeImage_Create(texture_id, GL_TEXTURE_EXTERNAL_OES); if (ohos_external_gl->nativeImage_ == nullptr) { FML_DLOG(ERROR) << "Error with OH_NativeImage_Create"; return surface_id; } - void* contextData = new OhosImageFrameData(this, texture_id); - contextDatas_.insert(std::pair(texture_id, contextData)); - OH_OnFrameAvailableListener listener; - listener.context = contextData; - listener.onFrameAvailable = &PlatformViewOHOS::OnNativeImageFrameAvailable; - ret = OH_NativeImage_SetOnFrameAvailableListener( - ohos_external_gl->nativeImage_, listener); - if (ret != 0) { - FML_DLOG(ERROR) - << "Error with OH_NativeImage_SetOnFrameAvailableListener"; - return surface_id; - } ret = OH_NativeImage_GetSurfaceId(ohos_external_gl->nativeImage_, &surface_id); ohos_external_gl->first_update_ = false; @@ -484,6 +461,7 @@ uint64_t PlatformViewOHOS::RegisterExternalTexture(int64_t texture_id) } external_texture_gl_[texture_id] = ohos_external_gl; RegisterTexture(ohos_external_gl); + MarkTextureFrameAvailable(texture_id); } return surface_id; } @@ -501,54 +479,11 @@ void PlatformViewOHOS::SetTextureBufferSize( } } -void PlatformViewOHOS::OnNativeImageFrameAvailable(void* data) { - auto frameData = reinterpret_cast(data); - if (frameData == nullptr || frameData->context_ == nullptr) { - FML_DLOG(ERROR) - << "OnNativeImageFrameAvailable, frameData or context_ is null."; - return; - } - - if (frameData->context_->GetDestroyed()) { - FML_LOG(ERROR) << "OnNativeImageFrameAvailable NotifyDstroyed, will not " - "MarkTextureFrameAvailable"; - return; - } - - std::shared_ptr ohos_surface = - frameData->context_->ohos_surface_; - const TaskRunners task_runners = frameData->context_->task_runners_; - if (ohos_surface) { - fml::TaskRunner::RunNowOrPostTask( - task_runners.GetPlatformTaskRunner(), [frameData]() { - if (frameData->context_->GetDestroyed()) { - FML_LOG(ERROR) << "OnNativeImageFrameAvailable NotifyDstroyed, " - "will not MarkTextureFrameAvailable"; - return; - } - frameData->context_->MarkTextureFrameAvailable( - frameData->texture_id_); - }); - } -} - void PlatformViewOHOS::UnRegisterExternalTexture(int64_t texture_id) { FML_DLOG(INFO) << "PlatformViewOHOS::UnRegisterExternalTexture, texture_id=" << texture_id; external_texture_gl_.erase(texture_id); UnregisterTexture(texture_id); - std::map::iterator it = contextDatas_.find(texture_id); - if (it != contextDatas_.end()) { - if (it->second != nullptr) { - OhosImageFrameData* data = - reinterpret_cast(it->second); - task_runners_.GetPlatformTaskRunner()->PostDelayedTask( - [data_ = data]() { delete data_; }, fml::TimeDelta::FromSeconds(2)); - data = nullptr; - it->second = nullptr; - } - contextDatas_.erase(texture_id); - } } void PlatformViewOHOS::RegisterExternalTextureByPixelMap( @@ -560,7 +495,7 @@ void PlatformViewOHOS::RegisterExternalTextureByPixelMap( iter->second->DispatchPixelMap(pixelMap); } else { std::shared_ptr ohos_external_gl = - std::make_shared(texture_id, ohos_surface_); + std::make_shared(texture_id, ohos_surface_, delegate_); external_texture_gl_[texture_id] = ohos_external_gl; RegisterTexture(ohos_external_gl); ohos_external_gl->DispatchPixelMap(pixelMap); @@ -613,10 +548,4 @@ void PlatformViewOHOS::RunTask(OHOS_THREAD_TYPE type, const fml::closure& task) fml::TaskRunner::RunNowOrPostTask(TaskRunnerPtr, task); } -OhosImageFrameData::OhosImageFrameData(PlatformViewOHOS* context, - int64_t texture_id) - : context_(context), texture_id_(texture_id) {} - -OhosImageFrameData::~OhosImageFrameData() = default; - } // namespace flutter diff --git a/shell/platform/ohos/platform_view_ohos.h b/shell/platform/ohos/platform_view_ohos.h index 8e1b233b3b..eb853a3e4f 100644 --- a/shell/platform/ohos/platform_view_ohos.h +++ b/shell/platform/ohos/platform_view_ohos.h @@ -154,7 +154,6 @@ class PlatformViewOHOS final : public PlatformView { std::shared_ptr surface_factory_; std::map> external_texture_gl_; - std::map contextDatas_; std::atomic isDestroyed_; @@ -209,19 +208,6 @@ class PlatformViewOHOS final : public PlatformView { FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewOHOS); - static void OnNativeImageFrameAvailable(void *data); -}; - -class OhosImageFrameData { - public: - OhosImageFrameData(PlatformViewOHOS* context, - int64_t texture_id); - - ~OhosImageFrameData(); - - PlatformViewOHOS* context_; - - int64_t texture_id_; }; } // namespace flutter -- Gitee From 1c2e06f517f7cb33fd4828dc2a1d633c4e2bfb2f Mon Sep 17 00:00:00 2001 From: li_guoning Date: Fri, 22 Nov 2024 10:44:32 +0800 Subject: [PATCH 127/151] =?UTF-8?q?=E9=80=82=E9=85=8Dx86=E6=A8=A1=E6=8B=9F?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: li_guoning --- attachment/repos/build.patch | 90 ++++++++------ attachment/repos/dart.patch0 | 227 ++++++++++++++++++++++++++++++++++- attachment/scripts/ohos.py | 17 ++- tools/gn | 4 +- 4 files changed, 285 insertions(+), 53 deletions(-) diff --git a/attachment/repos/build.patch b/attachment/repos/build.patch index bbe17f9809..84c50014e1 100644 --- a/attachment/repos/build.patch +++ b/attachment/repos/build.patch @@ -102,16 +102,16 @@ index b8d0f47..a3d1ed9 100644 @@ -313,7 +334,7 @@ if (!is_clang && using_sanitizer) { is_clang = true } - + -use_flutter_cxx = is_clang && (is_linux || is_android || is_mac || is_ios) +use_flutter_cxx = is_clang && (is_linux || is_android || is_mac || is_ios || is_ohos ) - + if (is_msan && !is_linux) { assert(false, "Memory sanitizer is only available on Linux.") @@ -365,7 +386,9 @@ if (is_posix) { ] } - + -if (is_linux) { +if (is_ohos || (is_linux && host_os == "mac")) { + _native_compiler_configs += [ "//build/config/ohos:sdk" ] @@ -160,7 +160,7 @@ index b8d0f47..a3d1ed9 100644 if (is_clang) { host_toolchain = "//build/toolchain/linux:clang_$host_cpu" diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn -index ba20010..17e0487 100644 +index ba20010..5f27c8c 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn @@ -191,10 +191,16 @@ config("compiler") { @@ -185,7 +185,7 @@ index ba20010..17e0487 100644 } else if (current_cpu == "x86") { cflags += [ "-m32" ] @@ -315,7 +321,7 @@ config("compiler") { - + # Linux/Android common flags setup. # --------------------------------- - if (is_linux || is_android) { @@ -193,8 +193,8 @@ index ba20010..17e0487 100644 cflags += [ "-fPIC", "-pipe", # Use pipes for communicating between sub-processes. Faster. -@@ -334,7 +340,16 @@ config("compiler") { - +@@ -334,7 +340,28 @@ config("compiler") { + # Linux-specific compiler flags setup. # ------------------------------------ - if (is_linux) { @@ -202,7 +202,19 @@ index ba20010..17e0487 100644 + cflags += [ "-pthread" ] + ldflags += [ "-pthread" ] + -+ if (current_cpu == "arm64") { ++ if (current_cpu == "x86") { ++ cflags += [ "--target=x86-linux-ohos" ] ++ ldflags += [ "--target=x86-linux-ohos" ] ++ cflags += [ "-DBORINGSSL_CLANG_SUPPORTS_DOT_ARCH" ] ++ } else if (current_cpu == "x64") { ++ cflags += [ "--target=x86_64-linux-ohos" ] ++ ldflags += [ "--target=x86_64-linux-ohos" ] ++ cflags += [ "-DBORINGSSL_CLANG_SUPPORTS_DOT_ARCH" ] ++ } else if (current_cpu == "arm") { ++ cflags += [ "--target=aarch-linux-ohos" ] ++ ldflags += [ "--target=aarch-linux-ohos" ] ++ cflags += [ "-DBORINGSSL_CLANG_SUPPORTS_DOT_ARCH" ] ++ } else if (current_cpu == "arm64") { + cflags += [ "--target=aarch64-linux-ohos" ] + ldflags += [ "--target=aarch64-linux-ohos" ] + cflags += [ "-DBORINGSSL_CLANG_SUPPORTS_DOT_ARCH" ] @@ -210,8 +222,8 @@ index ba20010..17e0487 100644 + } else if (is_linux) { cflags += [ "-pthread" ] ldflags += [ "-pthread" ] - -@@ -521,9 +536,13 @@ config("runtime_library") { + +@@ -521,9 +548,13 @@ config("runtime_library") { ldflags += [ "-nostdlib++" ] } include_dirs = [ @@ -224,9 +236,9 @@ index ba20010..17e0487 100644 + include_dirs += [ "//third_party/libcxx/include" ] + } } - + # Android standard library setup. -@@ -860,17 +879,35 @@ config("optimize") { +@@ -860,12 +891,14 @@ config("optimize") { cflags = [ "-Oz" ] + common_optimize_on_cflags # Favor size over speed. } else if (is_wasm) { cflags = [ "-Oz" ] @@ -235,34 +247,13 @@ index ba20010..17e0487 100644 } else { cflags = [ "-O2" ] + common_optimize_on_cflags } - + lto_flags = [] - if (enable_lto && (is_ios || is_android || is_fuchsia || is_wasm)) { + if (enable_lto && (is_ios || is_android || is_fuchsia || is_wasm || is_ohos)) { lto_flags += [ "-flto" ] } - -+ if (is_ohos) { -+ cflags += [ -+ "-mcpu=tsv110", -+ "-fwhole-program-vtables", -+ ] -+ } -+ - ldflags = common_optimize_on_ldflags + lto_flags - cflags += lto_flags -+ -+ if (is_ohos) { -+ ldflags += [ -+ "-Wl,--lto-O2", -+ "-Wl,--plugin-opt=-mcpu=tsv110", -+ "-Wl,-mllvm", -+ "-Wl,-wholeprogramdevirt-check=fallback", -+ ] -+ } - } - - # Turn off optimizations. + diff --git a/build/config/ohos/BUILD.gn b/build/config/ohos/BUILD.gn new file mode 100644 index 0000000..b2675d2 @@ -300,10 +291,10 @@ index 0000000..b2675d2 +} diff --git a/build/config/ohos/config.gni b/build/config/ohos/config.gni new file mode 100644 -index 0000000..0022d70 +index 0000000..add7249 --- /dev/null +++ b/build/config/ohos/config.gni -@@ -0,0 +1,13 @@ +@@ -0,0 +1,32 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. @@ -311,7 +302,26 @@ index 0000000..0022d70 +# This file contains common system config stuff for the Ohos build. + +if (is_ohos) { -+ if (current_cpu == "arm64") { ++ # Defines host_os ++ if (host_os == "linux") { ++ ohos_host_os = "linux" ++ } else if (host_os == "mac") { ++ ohos_host_os = "darwin" ++ } else if (host_os == "win") { ++ ohos_host_os = "win" ++ } else { ++ assert(false, "Need Ohos toolchain support for your build OS.") ++ } ++ ++ ++ # ABI ------------------------------------------------------------------------ ++ if (current_cpu == "x86") { ++ ohos_app_abi = "x86" ++ } else if (current_cpu == "x64") { ++ ohos_app_abi = "x86_64" ++ } else if (current_cpu == "arm") { ++ ohos_app_abi = "armeabi-v7a" ++ } else if (current_cpu == "arm64") { + ohos_app_abi = "arm64-v8a" + } else { + assert(false, "Unknown Ohos ABI: " + current_cpu) @@ -864,7 +874,7 @@ index cad6cbc..c17950b 100644 +++ b/build/secondary/third_party/glfw/BUILD.gn @@ -47,6 +47,34 @@ source_set("glfw") { ] - + defines = [ "_GLFW_WIN32" ] + } else if (is_ohos) { + sources += [ @@ -914,6 +924,6 @@ index 65b1623..a89742a 100644 + readelf = "${toolchain_bin}/llvm-readelf" + nm = "${toolchain_bin}/llvm-nm" + strip = "${toolchain_bin}/llvm-strip" - + target_triple_flags = "--target=${custom_target_triple}" sysroot_flags = "--sysroot ${custom_sysroot}" diff --git a/attachment/repos/dart.patch0 b/attachment/repos/dart.patch0 index 04ca043cec..8094cc2e31 100644 --- a/attachment/repos/dart.patch0 +++ b/attachment/repos/dart.patch0 @@ -1,4 +1,4 @@ -diff --git a/pkg/dds/lib/dds.dart b/pkg/dds/lib/dds.dart +diff --git a/pkg/dds/lib/dds.dart b/pkg/dds/lib/dds.dart index 177a9265649..c7038c56ad7 100644 --- a/pkg/dds/lib/dds.dart +++ b/pkg/dds/lib/dds.dart @@ -75,6 +75,60 @@ index 33be98fc0aa..eda146a0580 100644 String? get authCode => _authCode; String? _authCode; +diff --git a/pkg/vm/lib/transformations/ffi/abi.dart b/pkg/vm/lib/transformations/ffi/abi.dart +index cc2d86bafd7..e703419eed7 100644 +--- a/pkg/vm/lib/transformations/ffi/abi.dart ++++ b/pkg/vm/lib/transformations/ffi/abi.dart +@@ -40,6 +40,7 @@ enum _OS { + linux, + macos, + windows, ++ ohos, + } + + /// An application binary interface (ABI). +@@ -71,6 +72,9 @@ class Abi { + /// The application binary interface for Fuchsia on the X64 architecture. + static const fuchsiaX64 = _fuchsiaX64; + ++ /// The application binary interface for Ohos on the X64 architecture. ++ static const ohosX64 = _ohosX64; ++ + /// The application binary interface for iOS on the Arm architecture. + static const iosArm = _iosArm; + +@@ -131,6 +135,7 @@ class Abi { + androidX64, + fuchsiaArm64, + fuchsiaX64, ++ ohosX64, + iosArm, + iosArm64, + iosX64, +@@ -176,6 +181,7 @@ class Abi { + static const _androidX64 = Abi._(_Architecture.x64, _OS.android); + static const _fuchsiaArm64 = Abi._(_Architecture.arm64, _OS.fuchsia); + static const _fuchsiaX64 = Abi._(_Architecture.x64, _OS.fuchsia); ++ static const _ohosX64 = Abi._(_Architecture.x64, _OS.ohos); + static const _iosArm = Abi._(_Architecture.arm, _OS.ios); + static const _iosArm64 = Abi._(_Architecture.arm64, _OS.ios); + static const _iosX64 = Abi._(_Architecture.x64, _OS.ios); +@@ -200,6 +206,7 @@ const Map abiNames = { + Abi.androidX64: 'androidX64', + Abi.fuchsiaArm64: 'fuchsiaArm64', + Abi.fuchsiaX64: 'fuchsiaX64', ++ Abi.ohosX64: 'ohosX64', + Abi.iosArm: 'iosArm', + Abi.iosArm64: 'iosArm64', + Abi.iosX64: 'iosX64', +@@ -239,6 +246,7 @@ const Map> nonSizeAlignment = { + // _wordSize64 + Abi.androidArm64: _wordSize64, + Abi.androidX64: _wordSize64, ++ Abi.ohosX64: _wordSize64, + Abi.fuchsiaArm64: _wordSize64, + Abi.fuchsiaX64: _wordSize64, + Abi.iosArm64: _wordSize64, diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn index 13bfd0a724b..042b6a45f7e 100644 --- a/runtime/BUILD.gn @@ -5575,27 +5629,28 @@ index 66fa5a8d564..cc5eb834b3d 100644 #if DART_TARGET_OS_MACOS_IOS #define DART_TARGET_OS_NAME IOS diff --git a/runtime/vm/compiler/ffi/abi.h b/runtime/vm/compiler/ffi/abi.h -index b693ef85255..54b15f48890 100644 +index b693ef85255..6a3f42bd949 100644 --- a/runtime/vm/compiler/ffi/abi.h +++ b/runtime/vm/compiler/ffi/abi.h -@@ -24,6 +24,8 @@ enum class Abi { +@@ -24,6 +24,9 @@ enum class Abi { kAndroidArm64, kAndroidIA32, kAndroidX64, + kOhosArm, + kOhosArm64, ++ kOhosX64, kFuchsiaArm64, kFuchsiaX64, kIOSArm, -@@ -49,9 +51,9 @@ const int64_t num_abis = static_cast(Abi::kWindowsX64) + 1; +@@ -49,9 +52,9 @@ const int64_t num_abis = static_cast(Abi::kWindowsX64) + 1; // - runtime/vm/compiler/frontend/kernel_to_il.cc static_assert(static_cast(Abi::kAndroidArm) == 0, "Enum value unexpected."); -static_assert(static_cast(Abi::kWindowsX64) == 19, -+static_assert(static_cast(Abi::kWindowsX64) == 21, ++static_assert(static_cast(Abi::kWindowsX64) == 22, "Enum value unexpected."); -static_assert(num_abis == 20, "Enum value unexpected."); -+static_assert(num_abis == 22, "Enum value unexpected."); ++static_assert(num_abis == 23, "Enum value unexpected."); // The target ABI. Defines sizes and alignment of native types. Abi TargetAbi(); @@ -7619,6 +7674,166 @@ index b7e5be3eab5..8a8f873f6c5 100644 bool _isAllowedOrigin(String origin) { Uri uri; +diff --git a/sdk/lib/ffi/abi.dart b/sdk/lib/ffi/abi.dart +index e6f08b37d25..5af605a8764 100644 +--- a/sdk/lib/ffi/abi.dart ++++ b/sdk/lib/ffi/abi.dart +@@ -34,6 +34,9 @@ class Abi { + /// The application binary interface for Fuchsia on the X64 architecture. + static const fuchsiaX64 = _fuchsiaX64; + ++ /// The application binary interface for Ohos on the X64 architecture. ++ static const ohosX64 = _ohosX64; ++ + /// The application binary interface for iOS on the Arm architecture. + static const iosArm = _iosArm; + +@@ -94,6 +97,7 @@ class Abi { + androidX64, + fuchsiaArm64, + fuchsiaX64, ++ ohosX64, + iosArm, + iosArm64, + iosX64, +@@ -136,6 +140,7 @@ class Abi { + static const _androidX64 = Abi._(_Architecture.x64, _OS.android); + static const _fuchsiaArm64 = Abi._(_Architecture.arm64, _OS.fuchsia); + static const _fuchsiaX64 = Abi._(_Architecture.x64, _OS.fuchsia); ++ static const _ohosX64 = Abi._(_Architecture.x64, _OS.ohos); + static const _iosArm = Abi._(_Architecture.arm, _OS.ios); + static const _iosArm64 = Abi._(_Architecture.arm64, _OS.ios); + static const _iosX64 = Abi._(_Architecture.x64, _OS.ios); +@@ -170,4 +175,5 @@ enum _OS { + linux, + macos, + windows, ++ ohos, + } +diff --git a/sdk/lib/ffi/c_type.dart b/sdk/lib/ffi/c_type.dart +index ee358c2f79d..1f9e629beb9 100644 +--- a/sdk/lib/ffi/c_type.dart ++++ b/sdk/lib/ffi/c_type.dart +@@ -29,6 +29,7 @@ part of dart.ffi; + Abi.androidX64: Int8(), + Abi.fuchsiaArm64: Uint8(), + Abi.fuchsiaX64: Int8(), ++ Abi.ohosX64: Int8(), + Abi.iosArm: Int8(), + Abi.iosArm64: Int8(), + Abi.iosX64: Int8(), +@@ -66,6 +67,7 @@ class Char extends AbiSpecificInteger { + Abi.androidX64: Int8(), + Abi.fuchsiaArm64: Int8(), + Abi.fuchsiaX64: Int8(), ++ Abi.ohosX64: Int8(), + Abi.iosArm: Int8(), + Abi.iosArm64: Int8(), + Abi.iosX64: Int8(), +@@ -103,6 +105,7 @@ class SignedChar extends AbiSpecificInteger { + Abi.androidX64: Uint8(), + Abi.fuchsiaArm64: Uint8(), + Abi.fuchsiaX64: Uint8(), ++ Abi.ohosX64: Uint8(), + Abi.iosArm: Uint8(), + Abi.iosArm64: Uint8(), + Abi.iosX64: Uint8(), +@@ -140,6 +143,7 @@ class UnsignedChar extends AbiSpecificInteger { + Abi.androidX64: Int16(), + Abi.fuchsiaArm64: Int16(), + Abi.fuchsiaX64: Int16(), ++ Abi.ohosX64: Int16(), + Abi.iosArm: Int16(), + Abi.iosArm64: Int16(), + Abi.iosX64: Int16(), +@@ -177,6 +181,7 @@ class Short extends AbiSpecificInteger { + Abi.androidX64: Uint16(), + Abi.fuchsiaArm64: Uint16(), + Abi.fuchsiaX64: Uint16(), ++ Abi.ohosX64: Uint16(), + Abi.iosArm: Uint16(), + Abi.iosArm64: Uint16(), + Abi.iosX64: Uint16(), +@@ -214,6 +219,7 @@ class UnsignedShort extends AbiSpecificInteger { + Abi.androidX64: Int32(), + Abi.fuchsiaArm64: Int32(), + Abi.fuchsiaX64: Int32(), ++ Abi.ohosX64: Int32(), + Abi.iosArm: Int32(), + Abi.iosArm64: Int32(), + Abi.iosX64: Int32(), +@@ -251,6 +257,7 @@ class Int extends AbiSpecificInteger { + Abi.androidX64: Uint32(), + Abi.fuchsiaArm64: Uint32(), + Abi.fuchsiaX64: Uint32(), ++ Abi.ohosX64: Uint32(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint32(), + Abi.iosX64: Uint32(), +@@ -289,6 +296,7 @@ class UnsignedInt extends AbiSpecificInteger { + Abi.androidX64: Int64(), + Abi.fuchsiaArm64: Int64(), + Abi.fuchsiaX64: Int64(), ++ Abi.ohosX64: Int64(), + Abi.iosArm: Int32(), + Abi.iosArm64: Int64(), + Abi.iosX64: Int64(), +@@ -327,6 +335,7 @@ class Long extends AbiSpecificInteger { + Abi.androidX64: Uint64(), + Abi.fuchsiaArm64: Uint64(), + Abi.fuchsiaX64: Uint64(), ++ Abi.ohosX64: Uint64(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint64(), + Abi.iosX64: Uint64(), +@@ -364,6 +373,7 @@ class UnsignedLong extends AbiSpecificInteger { + Abi.androidX64: Int64(), + Abi.fuchsiaArm64: Int64(), + Abi.fuchsiaX64: Int64(), ++ Abi.ohosX64: Int64(), + Abi.iosArm: Int64(), + Abi.iosArm64: Int64(), + Abi.iosX64: Int64(), +@@ -401,6 +411,7 @@ class LongLong extends AbiSpecificInteger { + Abi.androidX64: Uint64(), + Abi.fuchsiaArm64: Uint64(), + Abi.fuchsiaX64: Uint64(), ++ Abi.ohosX64: Uint64(), + Abi.iosArm: Uint64(), + Abi.iosArm64: Uint64(), + Abi.iosX64: Uint64(), +@@ -433,6 +444,7 @@ class UnsignedLongLong extends AbiSpecificInteger { + Abi.androidX64: Int64(), + Abi.fuchsiaArm64: Int64(), + Abi.fuchsiaX64: Int64(), ++ Abi.ohosX64: Int64(), + Abi.iosArm: Int32(), + Abi.iosArm64: Int64(), + Abi.iosX64: Int64(), +@@ -466,6 +478,7 @@ class IntPtr extends AbiSpecificInteger { + Abi.androidX64: Uint64(), + Abi.fuchsiaArm64: Uint64(), + Abi.fuchsiaX64: Uint64(), ++ Abi.ohosX64: Uint64(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint64(), + Abi.iosX64: Uint64(), +@@ -499,6 +512,7 @@ class UintPtr extends AbiSpecificInteger { + Abi.androidX64: Uint64(), + Abi.fuchsiaArm64: Uint64(), + Abi.fuchsiaX64: Uint64(), ++ Abi.ohosX64: Uint64(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint64(), + Abi.iosX64: Uint64(), +@@ -535,6 +549,7 @@ class Size extends AbiSpecificInteger { + Abi.androidX64: Uint32(), + Abi.fuchsiaArm64: Uint32(), + Abi.fuchsiaX64: Int32(), ++ Abi.ohosX64: Int32(), + Abi.iosArm: Int32(), + Abi.iosArm64: Int32(), + Abi.iosX64: Int32(), diff --git a/sdk_args.gni b/sdk_args.gni index 4b2a1e4ea63..a864344ee8d 100644 --- a/sdk_args.gni diff --git a/attachment/scripts/ohos.py b/attachment/scripts/ohos.py index 2d21f7848f..d60c405775 100644 --- a/attachment/scripts/ohos.py +++ b/attachment/scripts/ohos.py @@ -28,6 +28,12 @@ from datetime import datetime SUPPORT_BUILD_NAMES = ("clean", "config", "har", "compile", "zip", "zip2", "upload") SUPPORT_BUILD_TYPES = ("debug", "profile", "release") +SUPPORT_ABIS = { + "x86": "x86", + "x64": "x86_64", + "arm": "armeabi-v7a", + "arm64": "arm64-v8a", +} DIR_ROOT = os.path.abspath(os.path.join(sys.argv[0], os.pardir)) OS_NAME = platform.system().lower() IS_WINDOWS = OS_NAME.startswith("win") @@ -61,14 +67,12 @@ class BuildInfo: buildType="release", targetOS="ohos", targetArch="arm64", - targetTriple="arm64-%s-ohos" % OS_NAME, - abi="arm64-v8a", ): self.buildType = buildType self.targetOS = targetOS self.targetArch = targetArch - self.targetTriple = targetTriple - self.abi = abi + self.targetTriple = "%s-%s-%s" % (targetArch, OS_NAME, targetOS) + self.abi = SUPPORT_ABIS[targetArch] def __repr__(self): return "BuildInfo(buildType=%s)" % (self.buildType) @@ -333,6 +337,9 @@ def addParseParam(parser): parser.add_argument( "--har-unstripped", action="store_true", help="Use so.unstripped or not." ) + parser.add_argument( + "--ohos-cpu", type=str, choices=['x64', 'x86', 'arm64', 'arm'], default="arm64" + ) def updateCode(args): @@ -365,7 +372,7 @@ def buildByNameAndType(args): for buildType in SUPPORT_BUILD_TYPES: if not buildType in buildTypes: continue - buildInfo = BuildInfo(buildType=buildType) + buildInfo = BuildInfo(buildType=buildType, targetArch=args.ohos_cpu) for buildName in SUPPORT_BUILD_NAMES: if not buildName in buildNames: continue diff --git a/tools/gn b/tools/gn index ccbb3b75e9..e0845814ef 100755 --- a/tools/gn +++ b/tools/gn @@ -344,8 +344,8 @@ def to_gn_args(args): gn_args['target_os'] = args.target_os gn_args['target_cpu'] = get_target_cpu(args) gn_args['dart_target_arch'] = gn_args['target_cpu'] - if (args.target_os == 'ohos'): - gn_args['host_cpu'] = get_host_cpu() + #if (args.target_os == 'ohos'): + # gn_args['host_cpu'] = get_host_cpu() print("ARGS.target_os:%s-%s" % (args.target_os,gn_args['target_os'] ) ) # We cannot cross-compile for 32 bit arm on a Windows host. We work around -- Gitee From d0b910437095daa498c16ae682ce0b4db63a6954 Mon Sep 17 00:00:00 2001 From: li_guoning Date: Fri, 22 Nov 2024 15:19:22 +0800 Subject: [PATCH 128/151] =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=B8=8D=E5=BF=85?= =?UTF-8?q?=E8=A6=81=E7=9A=84=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: li_guoning --- tools/gn | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/gn b/tools/gn index e0845814ef..ee44e2512a 100755 --- a/tools/gn +++ b/tools/gn @@ -344,8 +344,6 @@ def to_gn_args(args): gn_args['target_os'] = args.target_os gn_args['target_cpu'] = get_target_cpu(args) gn_args['dart_target_arch'] = gn_args['target_cpu'] - #if (args.target_os == 'ohos'): - # gn_args['host_cpu'] = get_host_cpu() print("ARGS.target_os:%s-%s" % (args.target_os,gn_args['target_os'] ) ) # We cannot cross-compile for 32 bit arm on a Windows host. We work around -- Gitee From 267d464fa8a611aed35c7e9e3f8ba0a469496e18 Mon Sep 17 00:00:00 2001 From: liujiake Date: Wed, 27 Nov 2024 10:44:46 +0800 Subject: [PATCH 129/151] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A3=80=E8=A7=86?= =?UTF-8?q?=E6=84=8F=E8=A7=81=EF=BC=88=E4=BF=AE=E5=A4=8D=E5=86=85=E5=AD=98?= =?UTF-8?q?=E6=B3=84=E6=BC=8F=EF=BC=8C=E5=8F=96=E6=B6=88=E5=8E=9F=E5=8F=AF?= =?UTF-8?q?=E7=94=A8=E5=B8=A7=E5=88=A4=E6=96=AD=E6=A0=87=E5=BF=97=EF=BC=9B?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=88=90=E5=91=98=E5=91=BD=E5=90=8D=EF=BC=9B?= =?UTF-8?q?=E5=87=8F=E5=B0=91=E4=BB=A3=E7=A0=81=E5=B5=8C=E5=A5=97=E6=B7=B1?= =?UTF-8?q?=E5=BA=A6=EF=BC=9B=E4=BF=AE=E6=94=B9log=E7=AD=89=E7=BA=A7?= =?UTF-8?q?=E3=80=82=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- .../ohos/ohos_external_texture_gl.cpp | 48 ++++++++++--------- .../platform/ohos/ohos_external_texture_gl.h | 14 +++--- shell/platform/ohos/platform_view_ohos.cpp | 1 - 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 6dd6962627..b57a54df8b 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -42,7 +42,6 @@ constexpr const char *EGL_GET_PLATFORM_DISPLAY_EXT = "eglGetPlatformDisplayEXT"; constexpr uint32_t WHITE_COLOR = 0xFFFFFFFF; const SkScalar DEFAULT_MATRIX[] = {1, 0, 0, 0, -1, 1, 0, 0, 1}; -const int UPDATE_FRAME_COUNT = 1; static int PixelMapToWindowFormat(PIXEL_FORMAT pixel_format) { @@ -126,14 +125,10 @@ void OnNativeImageFrameAvailable(void *data) { auto frameData = reinterpret_cast(data); if (frameData == nullptr) { - FML_DLOG(ERROR) << "OnNativeImageFrameAvailable, frameData is null."; + FML_LOG(ERROR) << "OnNativeImageFrameAvailable, frameData is null."; return; } - if (!frameData->t) { - FML_DLOG(ERROR) << "OnNativeImageFrameAvailable, frameData value is not valid."; - return; - } - frameData->t->delegate_.OnPlatformViewMarkTextureFrameAvailable(frameData->texture_id_); + frameData->OnPlatformViewMarkTextureFrameAvailable(); } void OHOSExternalTextureGL::Attach() @@ -179,8 +174,12 @@ void OHOSExternalTextureGL::Attach() listener.onFrameAvailable = OnNativeImageFrameAvailable; ret = OH_NativeImage_SetOnFrameAvailableListener(nativeImage_, listener); if (ret != 0) { - FML_DLOG(ERROR) + FML_LOG(ERROR) << "Error with OH_NativeImage_SetOnFrameAvailableListener"; + if (frameData_ != nullptr) { + delete (OhosImageFrameData *)frameData_; + frameData_ = nullptr; + } return; } @@ -204,17 +203,12 @@ void OHOSExternalTextureGL::Paint(PaintContext& context, if (pixelMap_ != nullptr) { // 外接纹理图片场景 ProducePixelMapToNativeImage(); - newFrameCount++; Update(); } } - if (!freeze && newFrameCount > 0) { - new_frame_ready_ = false; - newFrameCount--; - } GrGLTextureInfo textureInfo; - if (!freeze && !first_update_ && !isEmulator_ && !new_frame_ready_ && pixelMap_ == nullptr) { + if (!freeze && !first_update_ && !isEmulator_ && pixelMap_ == nullptr) { setBackground(bounds.width(), bounds.height()); textureInfo = {GL_TEXTURE_EXTERNAL_OES, backGroundTextureName_, GL_RGBA8_OES}; } else { @@ -272,8 +266,6 @@ void OHOSExternalTextureGL::OnGrContextDestroyed() void OHOSExternalTextureGL::MarkNewFrameAvailable() { FML_DLOG(INFO) << " OHOSExternalTextureGL::MarkNewFrameAvailable"; - new_frame_ready_ = true; - newFrameCount = UPDATE_FRAME_COUNT; if (state_ == AttachmentState::attached) { Update(); } @@ -714,12 +706,24 @@ void OHOSExternalTextureGL::DispatchBackGroundPixelMap(NativePixelMap* pixelMap) } OhosImageFrameData::OhosImageFrameData( - OHOSExternalTextureGL *t, - int64_t texture_id - ) - : t(t), - texture_id_(texture_id) {} + OHOSExternalTextureGL *ohosExternalTextureGL, + int64_t texture_id) + : ohosExternalTextureGL(ohosExternalTextureGL), + texture_id_(texture_id) +{} -OhosImageFrameData::~OhosImageFrameData() = default; +OhosImageFrameData::~OhosImageFrameData() +{ + ohosExternalTextureGL = nullptr; + texture_id_ = 0; +} + +void OhosImageFrameData::OnPlatformViewMarkTextureFrameAvailable() +{ + if(ohosExternalTextureGL != nullptr) { + PlatformView::Delegate& dalegate = ohosExternalTextureGL->delegate_; + dalegate.OnPlatformViewMarkTextureFrameAvailable(texture_id_); + } +} } // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h index b8da68b753..9d398ff977 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.h +++ b/shell/platform/ohos/ohos_external_texture_gl.h @@ -102,10 +102,6 @@ class OHOSExternalTextureGL : public flutter::Texture { AttachmentState state_; - bool new_frame_ready_ = false; - - std::atomic newFrameCount = 0; - GLuint texture_name_ = 0; GLuint backGroundTextureName_ = 0; @@ -140,11 +136,17 @@ class OHOSExternalTextureGL : public flutter::Texture { class OhosImageFrameData { public: - OhosImageFrameData(OHOSExternalTextureGL *t, int64_t texture_id); + OhosImageFrameData(OHOSExternalTextureGL *ohosExternalTextureGL, int64_t texture_id); + + OhosImageFrameData() = delete; ~OhosImageFrameData(); - OHOSExternalTextureGL *t; + void OnPlatformViewMarkTextureFrameAvailable(); + + private: + + OHOSExternalTextureGL *ohosExternalTextureGL; int64_t texture_id_; }; diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index 041ace656a..1f5fd79368 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -461,7 +461,6 @@ uint64_t PlatformViewOHOS::RegisterExternalTexture(int64_t texture_id) } external_texture_gl_[texture_id] = ohos_external_gl; RegisterTexture(ohos_external_gl); - MarkTextureFrameAvailable(texture_id); } return surface_id; } -- Gitee From 731e58acbfc6c5990ec9227230b542c3b62a08fc Mon Sep 17 00:00:00 2001 From: liujiake Date: Wed, 27 Nov 2024 12:15:59 +0800 Subject: [PATCH 130/151] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E5=91=8A=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- .../ohos/ohos_external_texture_gl.cpp | 40 +++++++++++-------- shell/platform/ohos/platform_view_ohos.h | 1 - 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index b57a54df8b..8cae8fc854 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -131,6 +131,27 @@ void OnNativeImageFrameAvailable(void *data) frameData->OnPlatformViewMarkTextureFrameAvailable(); } +void RegisterFrameAvailableListener(OH_NativeImage *nativeImage, OHOSExternalTextureGL *context) +{ + auto frameData = reinterpret_cast(context->frameData_); + if (frameData == nullptr) { + frameData = new OhosImageFrameData(context, context->Id()); + } + OH_OnFrameAvailableListener listener; + listener.context = frameData; + listener.onFrameAvailable = OnNativeImageFrameAvailable; + int64_t ret = OH_NativeImage_SetOnFrameAvailableListener(nativeImage, listener); + if (ret != 0) { + FML_LOG(ERROR) + << "Error with OH_NativeImage_SetOnFrameAvailableListener"; + if (frameData != nullptr) { + delete (OhosImageFrameData *)frameData; + frameData = nullptr; + } + return; + } +} + void OHOSExternalTextureGL::Attach() { FML_DLOG(INFO) << "Attach, texture_name_=" << texture_name_ @@ -166,22 +187,7 @@ void OHOSExternalTextureGL::Attach() FML_LOG(ERROR) << "OHOSExternalTextureGL OH_NativeImage_AttachContext err code:" << ret; } - if (frameData_ == nullptr) { - frameData_ = new OhosImageFrameData(this, Id()); - } - OH_OnFrameAvailableListener listener; - listener.context = frameData_; - listener.onFrameAvailable = OnNativeImageFrameAvailable; - ret = OH_NativeImage_SetOnFrameAvailableListener(nativeImage_, listener); - if (ret != 0) { - FML_LOG(ERROR) - << "Error with OH_NativeImage_SetOnFrameAvailableListener"; - if (frameData_ != nullptr) { - delete (OhosImageFrameData *)frameData_; - frameData_ = nullptr; - } - return; - } + RegisterFrameAvailableListener(nativeImage_, this); state_ = AttachmentState::attached; } else { @@ -720,7 +726,7 @@ OhosImageFrameData::~OhosImageFrameData() void OhosImageFrameData::OnPlatformViewMarkTextureFrameAvailable() { - if(ohosExternalTextureGL != nullptr) { + if (ohosExternalTextureGL != nullptr) { PlatformView::Delegate& dalegate = ohosExternalTextureGL->delegate_; dalegate.OnPlatformViewMarkTextureFrameAvailable(texture_id_); } diff --git a/shell/platform/ohos/platform_view_ohos.h b/shell/platform/ohos/platform_view_ohos.h index eb853a3e4f..c6dd57ccfb 100644 --- a/shell/platform/ohos/platform_view_ohos.h +++ b/shell/platform/ohos/platform_view_ohos.h @@ -207,7 +207,6 @@ class PlatformViewOHOS final : public PlatformView { void FireFirstFrameCallback(); FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewOHOS); - }; } // namespace flutter -- Gitee From c3f376a2670f260bd1ac794e8530af37dfb68a34 Mon Sep 17 00:00:00 2001 From: liujiake Date: Wed, 27 Nov 2024 12:40:58 +0800 Subject: [PATCH 131/151] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E5=91=8A=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- .../ohos/ohos_external_texture_gl.cpp | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 8cae8fc854..db3e2e42f1 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -131,25 +131,21 @@ void OnNativeImageFrameAvailable(void *data) frameData->OnPlatformViewMarkTextureFrameAvailable(); } -void RegisterFrameAvailableListener(OH_NativeImage *nativeImage, OHOSExternalTextureGL *context) +bool RegisterFrameAvailableListener(OH_NativeImage *nativeImage, OhosImageFrameData *frameData) { - auto frameData = reinterpret_cast(context->frameData_); if (frameData == nullptr) { - frameData = new OhosImageFrameData(context, context->Id()); + FML_LOG(ERROR) << "Error with RegisterFrameAvailableListener, frameData is null"; + return false; } OH_OnFrameAvailableListener listener; listener.context = frameData; listener.onFrameAvailable = OnNativeImageFrameAvailable; int64_t ret = OH_NativeImage_SetOnFrameAvailableListener(nativeImage, listener); if (ret != 0) { - FML_LOG(ERROR) - << "Error with OH_NativeImage_SetOnFrameAvailableListener"; - if (frameData != nullptr) { - delete (OhosImageFrameData *)frameData; - frameData = nullptr; - } - return; + FML_LOG(ERROR) << "Error with OH_NativeImage_SetOnFrameAvailableListener"; + return false; } + return true; } void OHOSExternalTextureGL::Attach() @@ -187,8 +183,14 @@ void OHOSExternalTextureGL::Attach() FML_LOG(ERROR) << "OHOSExternalTextureGL OH_NativeImage_AttachContext err code:" << ret; } - RegisterFrameAvailableListener(nativeImage_, this); - + if (frameData_ == nullptr) { + frameData_ = new OhosImageFrameData(this, Id()); + } + if (!RegisterFrameAvailableListener(nativeImage_, this)) { + delete (OhosImageFrameData *)frameData_; + frameData_ = nullptr; + return; + } state_ = AttachmentState::attached; } else { FML_LOG(ERROR) << "ResourceContextMakeCurrent failed"; -- Gitee From db735779dd032720630ffc12625563b5a8622cfd Mon Sep 17 00:00:00 2001 From: liujiake Date: Wed, 27 Nov 2024 13:08:26 +0800 Subject: [PATCH 132/151] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E5=91=8A=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- shell/platform/ohos/ohos_external_texture_gl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index db3e2e42f1..27a4caf4e0 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -186,7 +186,7 @@ void OHOSExternalTextureGL::Attach() if (frameData_ == nullptr) { frameData_ = new OhosImageFrameData(this, Id()); } - if (!RegisterFrameAvailableListener(nativeImage_, this)) { + if (!RegisterFrameAvailableListener(nativeImage_, (OhosImageFrameData *)frameData_)) { delete (OhosImageFrameData *)frameData_; frameData_ = nullptr; return; -- Gitee From fe22df3223ab469034fd40665027d5520ea5c3f0 Mon Sep 17 00:00:00 2001 From: liujiake Date: Wed, 27 Nov 2024 14:07:45 +0800 Subject: [PATCH 133/151] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E5=91=8A=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- shell/platform/ohos/ohos_external_texture_gl.cpp | 8 ++++---- shell/platform/ohos/ohos_external_texture_gl.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 27a4caf4e0..f52ffd1670 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -715,22 +715,22 @@ void OHOSExternalTextureGL::DispatchBackGroundPixelMap(NativePixelMap* pixelMap) OhosImageFrameData::OhosImageFrameData( OHOSExternalTextureGL *ohosExternalTextureGL, - int64_t texture_id) + int64_t textureId) : ohosExternalTextureGL(ohosExternalTextureGL), - texture_id_(texture_id) + textureId_(textureId) {} OhosImageFrameData::~OhosImageFrameData() { ohosExternalTextureGL = nullptr; - texture_id_ = 0; + textureId_ = 0; } void OhosImageFrameData::OnPlatformViewMarkTextureFrameAvailable() { if (ohosExternalTextureGL != nullptr) { PlatformView::Delegate& dalegate = ohosExternalTextureGL->delegate_; - dalegate.OnPlatformViewMarkTextureFrameAvailable(texture_id_); + dalegate.OnPlatformViewMarkTextureFrameAvailable(textureId_); } } diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h index 9d398ff977..6f8379cc0c 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.h +++ b/shell/platform/ohos/ohos_external_texture_gl.h @@ -136,7 +136,7 @@ class OHOSExternalTextureGL : public flutter::Texture { class OhosImageFrameData { public: - OhosImageFrameData(OHOSExternalTextureGL *ohosExternalTextureGL, int64_t texture_id); + OhosImageFrameData(OHOSExternalTextureGL *ohosExternalTextureGL, int64_t textureId); OhosImageFrameData() = delete; @@ -148,7 +148,7 @@ class OhosImageFrameData { OHOSExternalTextureGL *ohosExternalTextureGL; - int64_t texture_id_; + int64_t textureId_; }; } // namespace flutter -- Gitee From 89d804a0e1475e76c7e370df0cd227dd27359f86 Mon Sep 17 00:00:00 2001 From: xiaozn Date: Fri, 29 Nov 2024 17:22:06 +0800 Subject: [PATCH 134/151] =?UTF-8?q?fix=EF=BC=9A=E4=BF=AE=E5=A4=8DMediaQuer?= =?UTF-8?q?y=E7=BB=84=E4=BB=B6=E8=8E=B7=E5=8F=96ohos=E7=9C=9F=E6=9C=BA?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E4=B8=AD=E6=97=A0displayFeatures=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E8=BF=94=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xiaozn --- .../flutter/src/main/ets/view/FlutterView.ets | 135 +++++++++++++++++- 1 file changed, 131 insertions(+), 4 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index b54f8a6bc8..071aeffa81 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -27,6 +27,7 @@ import PlatformView, { Params } from '../plugin/platform/PlatformView'; import { JSON } from '@kit.ArkTS'; import { accessibility } from '@kit.AccessibilityKit'; import TextInputPlugin from '../plugin/editing/TextInputPlugin'; +import { BusinessError } from '@kit.BasicServicesKit'; const TAG = "FlutterViewTag"; @@ -47,6 +48,7 @@ export class ViewportMetrics { systemGestureInsetBottom: number = 0; systemGestureInsetLeft: number = 0; physicalTouchSlop: number = -1; + displayFeatures: ArrayList = new ArrayList(); clone(): ViewportMetrics { const copy = new ViewportMetrics(); @@ -66,6 +68,7 @@ export class ViewportMetrics { copy.systemGestureInsetBottom = this.systemGestureInsetBottom; copy.systemGestureInsetLeft = this.systemGestureInsetLeft; copy.physicalTouchSlop = this.physicalTouchSlop; + copy.displayFeatures = this.displayFeatures; return copy; } @@ -109,6 +112,72 @@ export class PlatformViewParas { } } +export class DisplayFeature { + bounds: Rect ; + type: DisplayFeatureType; + state: DisplayFeatureState; + + constructor(bounds: Rect, type: DisplayFeatureType, state: DisplayFeatureState) { + this.bounds = bounds; + this.type = type; + this.state = state; + } + + getBounds(): Rect { + return this.bounds; + } + getType(): DisplayFeatureType { + return this.type; + } + getState(): DisplayFeatureState { + return this.state; + } + + setBounds(bounds: Rect): void { + this.bounds = bounds; + } + setType(type: DisplayFeatureType): void { + this.type = type; + } + setState(state: DisplayFeatureState): void { + this.state = state; + } +} + +export class Rect { + left: number = 0.0; + top: number = 0.0; + width: number = 0.0; + height: number = 0.0; + + constructor(left: number, top: number, width: number, height: number) { + this.left = left; + this.top = top; + this.width = width; + this.height = height; + } +} + +export enum DisplayFeatureType { + UNKNOWN = 0, + FOLD = 1, + HINGE = 2, + CUTOUT = 3, +}; + +export enum DisplayFoldStatus { + FOLD_STATUS_UNKNOWN = 0, + FOLD_STATUS_EXPANDED = 1, + FOLD_STATUS_FOLDED = 2, + FOLD_STATUS_HALF_FOLDED = 3, +}; + +export enum DisplayFeatureState { + UNKNOWN = 0, + POSTURE_FLAT = 1, + POSTURE_HALF_OPENED = 2, +}; + export class FlutterView { private flutterEngine: FlutterEngine | null = null @@ -144,6 +213,49 @@ export class FlutterView { this.id = viewId this.displayInfo = display.getDefaultDisplaySync(); this.viewportMetrics.devicePixelRatio = this.displayInfo?.densityPixels; + this.viewportMetrics.physicalTouchSlop = 1.0 * this.displayInfo?.densityPixels; + let displayClass: Array = []; + let displayFeatures: ArrayList = new ArrayList(); + let state = 0; + let type = 0; + if (display.isFoldable()) { + if (display.getFoldStatus() == 2) { + type = DisplayFeatureType.HINGE + state = DisplayFeatureState.UNKNOWN; + } else if (display.getFoldStatus() == 1) { + type = DisplayFeatureType.FOLD; + state = DisplayFeatureState.POSTURE_FLAT; + } else if (display.getFoldStatus() == 3) { + type = DisplayFeatureType.FOLD; + state = DisplayFeatureState.POSTURE_HALF_OPENED; + } else { + type = DisplayFeatureType.UNKNOWN; + state = DisplayFeatureState.UNKNOWN; + } + display.getAllDisplays((err: BusinessError, data: Array) => { + displayClass = data; + const errCode: number = err.code; + if (errCode) { + console.error(`Failed to obtain all the display objects. Code: ${err.code}, message: ${err.message}`); + return; + } + displayClass.forEach(async feature => { + let bounds = await feature.getAvailableArea(); + Log.i(TAG, `bounds is : ${JSON.stringify(bounds)}`); + displayFeatures.add(new DisplayFeature(bounds, type, state)); + }) + this.viewportMetrics.displayFeatures = displayFeatures; + }); + } else { + type = DisplayFeatureType.CUTOUT; + state = DisplayFeatureState.UNKNOWN; + let promise = this.displayInfo.getAvailableArea(); + promise.then((data) =>{ + Log.i(TAG, `bounds is : ${JSON.stringify(data)}`); + displayFeatures.add(new DisplayFeature(data, type, state)); + }) + this.viewportMetrics.displayFeatures = displayFeatures; + } this.mainWindow = FlutterManager.getInstance() .getWindowStage(FlutterManager.getInstance().getUIAbility(context)) @@ -442,8 +554,23 @@ export class FlutterView { } private updateViewportMetrics(): boolean { + Log.i(TAG, 'isAttachedToFlutterEngine is:' + this.isAttachedToFlutterEngine); if (this.isAttachedToFlutterEngine()) { Log.i(TAG, 'updateViewportMetrics devicePixelRatio:' + this.viewportMetrics.devicePixelRatio) + const displayFeature = this.viewportMetrics.displayFeatures; + let displayFeaturesBounds: number[] = new Array(displayFeature.length * 4); + let displayFeaturesType: number[] = new Array(displayFeature.length); + let displayFeaturesState: number[] = new Array(displayFeature.length); + + for (let i = 0; i < displayFeature.length; i++) { + displayFeaturesBounds[4*i] = displayFeature[i].getBounds().left; + displayFeaturesBounds[4*i + 1] = displayFeature[i].getBounds().top; + displayFeaturesBounds[4*i + 2] = displayFeature[i].getBounds().width; + displayFeaturesBounds[4*i + 3] = displayFeature[i].getBounds().height; + displayFeaturesType[i] = displayFeature[i].getType(); + displayFeaturesState[i] = displayFeature[i].getState(); + } + this?.flutterEngine?.getFlutterNapi()?.setViewportMetrics(this.viewportMetrics.devicePixelRatio, this.viewportMetrics.physicalWidth, this.viewportMetrics.physicalHeight, @@ -460,10 +587,10 @@ export class FlutterView { this.viewportMetrics.systemGestureInsetBottom, this.viewportMetrics.systemGestureInsetLeft, this.viewportMetrics.physicalTouchSlop, - new Array(0), - new Array(0), - new Array(0)) - return true; + displayFeaturesBounds, + displayFeaturesState, + displayFeaturesType) + return true; } return false; } -- Gitee From 091ffb319af548bf19dd8d8f9603e452ce48130d Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 29 Nov 2024 17:39:22 +0800 Subject: [PATCH 135/151] =?UTF-8?q?feat:=E5=8D=95=E7=8B=AC=E5=B0=81?= =?UTF-8?q?=E8=A3=85=E6=97=A0=E9=9A=9C=E7=A2=8D=E5=8A=9F=E8=83=BD=E5=B9=B6?= =?UTF-8?q?=E7=BC=96=E8=AF=91libflutter=5Faccessibility.so,=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E5=8A=A8=E6=80=81=E9=93=BE=E6=8E=A5=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E5=85=BC=E5=AE=B9api12=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- shell/platform/ohos/BUILD.gn | 97 +- .../ohos_accessibility_bridge.cpp | 3520 +++++++++-------- .../accessibility/ohos_accessibility_bridge.h | 4 +- .../accessibility/ohos_accessibility_ddl.cpp | 287 ++ .../accessibility/ohos_accessibility_ddl.h | 82 + .../ohos_accessibility_interface.h | 703 ++++ .../platform/ohos/ohos_xcomponent_adapter.cpp | 18 +- shell/platform/ohos/ohos_xcomponent_adapter.h | 2 +- shell/platform/ohos/utils/ddl_utils.h | 25 + 9 files changed, 3112 insertions(+), 1626 deletions(-) create mode 100644 shell/platform/ohos/accessibility/ohos_accessibility_ddl.cpp create mode 100644 shell/platform/ohos/accessibility/ohos_accessibility_ddl.h create mode 100644 shell/platform/ohos/compatibility/ohos_accessibility_interface.h create mode 100644 shell/platform/ohos/utils/ddl_utils.h diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn index 4eec7abe9d..84548cee19 100644 --- a/shell/platform/ohos/BUILD.gn +++ b/shell/platform/ohos/BUILD.gn @@ -88,7 +88,9 @@ source_set("flutter_ohos_sources") { "./accessibility/ohos_accessibility_bridge.h", "./accessibility/ohos_accessibility_features.h", "./accessibility/ohos_accessibility_manager.h", - "./accessibility/native_accessibility_channel.h" + "./accessibility/native_accessibility_channel.h", + "./accessibility/ohos_accessibility_ddl.h", + "./utils/ddl_utils.h" ] #configs += [ "//flutter/shell/platform/ohos/config:gtk" ] @@ -123,7 +125,8 @@ source_set("flutter_ohos_sources") { "./accessibility/ohos_accessibility_bridge.cpp", "./accessibility/ohos_accessibility_features.cpp", "./accessibility/ohos_accessibility_manager.cpp", - "./accessibility/native_accessibility_channel.cpp" + "./accessibility/native_accessibility_channel.cpp", + "./accessibility/ohos_accessibility_ddl.cpp" ] # Set flag to stop headers being directly included (library users should not do this) @@ -161,6 +164,28 @@ source_set("flutter_ohos_sources") { } +# accessibility-relevant source set +source_set("flutter_ohos_accessibility_sources") { + public = _public_headers + [ + "./compatibility/ohos_accessibility_interface.h" + ] + + sources = [] + + # Set flag to stop headers being directly included (library users should not do this) + defines = [ + "FLUTTER_LINUX_COMPILATION", + "FLUTTER_ENGINE_NO_PROTOTYPES", + "OHOS_PLATFORM" , + "__MUSL__", + ] + + deps = [] + + public_deps = [] + ldflags = ["-lace_ndk.z"] +} + source_set("flutter_ohos_src") { configs += [ #"//flutter/shell/platform/ohos/config:gtk", @@ -234,16 +259,8 @@ shared_library("flutter_shell_native") { ldflags = ["--rtlib=compiler-rt", "-fuse-ld=lld", -# "-static-libstdc++", -# "-Wl", "--build-id=sha1", -# "-Wl,","--warn-shared-textrel", -# "-Wl,","--fatal-warnings -lunwind", -# "-Wl,","--no-undefined -Qunused-arguments", -# "-Wl,","-z,noexecstack" ] - #ldflags = [ "-Wl,-rpath,\$ORIGIN" ] - #ldflags += ["-L{$OHOS_NDK_LIB}","-lnative_window"] ldflags += ["-lnative_window"] ldflags += ["-lnative_vsync"] ldflags += ["-lace_napi.z"] @@ -254,7 +271,6 @@ shared_library("flutter_shell_native") { ldflags += ["-lrawfile.z"] ldflags += ["-lEGL"] ldflags += ["-lGLESv3"] - # ldflags += ["-lGLESv2"] ldflags += ["-limage_ndk.z"] ldflags += ["-lnative_image"] @@ -266,45 +282,19 @@ shared_library("flutter_shell_native") { public_configs = [ "//flutter:config" ] } -#copy("publish_headers_ohos") { -# sources = _public_headers -# outputs = [ "$root_out_dir/flutter_ohos/{{source_file_part}}" ] -#} - -#zip_bundle("flutter_gtk") { -# prefix = "$full_target_platform_name/" -# if (flutter_runtime_mode != "debug" || -# (flutter_runtime_mode == "debug" && target_cpu != "x64")) { -# prefix = "$full_target_platform_name-$flutter_runtime_mode/" -# } -# output = "${prefix}${full_target_platform_name}-flutter-gtk.zip" -# deps = [ -# ":flutter_ohos_gtk", -# ":publish_headers_ohos", -# "//third_party/dart/runtime/bin:gen_snapshot", -# ] -# sources = get_target_outputs(":publish_headers_ohos") -# tmp_files = [] -# foreach(source, sources) { -# tmp_files += [ -# { -# source = source -# destination = rebase_path(source, "$root_build_dir") -# }, -# ] -# } -# tmp_files += [ -# { -# source = "$root_build_dir/libflutter_${host_os}_gtk.so" -# destination = "libflutter_${host_os}_gtk.so" -# }, -# { -# source = "$root_build_dir/gen_snapshot" -# destination = "gen_snapshot" -# }, -# ] -# files = tmp_files -#} +# accessibility-relevant .so +shared_library("flutter_shell_native_accessibility") { + output_name = "flutter_accessibility" + deps = [ ":flutter_ohos_accessibility_sources" ] + + ldflags = ["--rtlib=compiler-rt", + "-fuse-ld=lld", + ] + + ldflags += ["-lace_ndk.z"] + + public_configs = [ "//flutter:config" ] +} declare_args() { embedding_artifact_id = "flutter_embedding_$flutter_runtime_mode" @@ -326,8 +316,10 @@ action("ohos_har") { if (stripped_symbols) { engine_library = "libflutter.so" + accessibility_library = "libflutter_accessibility.so" } else { engine_library = "so.unstripped/libflutter.so" + accessibility_library = "libflutter_accessibility.so" } inputs = [ @@ -351,6 +343,8 @@ action("ohos_har") { rebase_path("flutter.har", root_build_dir, root_build_dir), "--native_lib", rebase_path("$engine_library", root_build_dir, root_build_dir), + "--native_lib", + rebase_path("$accessibility_library", root_build_dir, root_build_dir), "--ohos_abi", ohos_app_abi, "--ohos_api_int", @@ -358,7 +352,8 @@ action("ohos_har") { ] deps = [ - ":flutter_shell_native" + ":flutter_shell_native", + ":flutter_shell_native_accessibility" ] if (flutter_runtime_mode == "profile") { diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 2d07986520..2e9522d681 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include "flutter/fml/logging.h" #include "flutter/shell/platform/ohos/ohos_logging.h" #include "flutter/shell/common/platform_view.h" @@ -36,24 +37,26 @@ LOGE("Failed arkui a11y function call, error code:%{public}d", RET); \ } \ } while (false) \ - + namespace flutter { + OhosAccessibilityBridge* OhosAccessibilityBridge::bridgeInstance = nullptr; OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() { - if(!bridgeInstance) { - bridgeInstance = new OhosAccessibilityBridge(); - } - return bridgeInstance; + if(!bridgeInstance) { + bridgeInstance = new OhosAccessibilityBridge(); + } + return bridgeInstance; } void OhosAccessibilityBridge::DestroyInstance() { - delete bridgeInstance; - bridgeInstance = nullptr; + delete bridgeInstance; + bridgeInstance = nullptr; } OhosAccessibilityBridge::OhosAccessibilityBridge() {} + /** * 监听当前ohos平台是否开启无障碍屏幕朗读服务 */ @@ -61,21 +64,21 @@ void OhosAccessibilityBridge::OnOhosAccessibilityStateChange( int64_t shellHolderId, bool ohosAccessibilityEnabled) { - native_shell_holder_id_ = shellHolderId; - nativeAccessibilityChannel_ = std::make_shared(); - accessibilityFeatures_ = std::make_shared(); + native_shell_holder_id_ = shellHolderId; + nativeAccessibilityChannel_ = std::make_shared(); + accessibilityFeatures_ = std::make_shared(); - if (ohosAccessibilityEnabled) { - nativeAccessibilityChannel_->OnOhosAccessibilityEnabled(native_shell_holder_id_); - } else { - accessibilityFeatures_->SetAccessibleNavigation(false, native_shell_holder_id_); - nativeAccessibilityChannel_->OnOhosAccessibilityDisabled(native_shell_holder_id_); - } + if (ohosAccessibilityEnabled) { + nativeAccessibilityChannel_->OnOhosAccessibilityEnabled(native_shell_holder_id_); + } else { + accessibilityFeatures_->SetAccessibleNavigation(false, native_shell_holder_id_); + nativeAccessibilityChannel_->OnOhosAccessibilityDisabled(native_shell_holder_id_); + } } void OhosAccessibilityBridge::SetNativeShellHolderId(int64_t id) { - this->native_shell_holder_id_ = id; + this->native_shell_holder_id_ = id; } /** @@ -85,87 +88,98 @@ void OhosAccessibilityBridge::updateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { - FML_DLOG(INFO) << ("OhosAccessibilityBridge::UpdateSemantics()"); - - // 当flutter页面更新时,自动请求id=0节点组件获焦(滑动组件除外) - if (IS_FLUTTER_NAVIGATE) { - RequestFocusWhenPageUpdate(); - IS_FLUTTER_NAVIGATE = false; - } + FML_DLOG(INFO) << ("OhosAccessibilityBridge::UpdateSemantics()"); - /** 获取并分析每个语义节点的更新属性 */ - for (auto& item : update) { - // 获取当前更新的节点node - const flutter::SemanticsNode& node = item.second; + // 当flutter页面更新时,自动请求id=0节点组件获焦(滑动组件除外) + if (IS_FLUTTER_NAVIGATE) { + RequestFocusWhenPageUpdate(); + IS_FLUTTER_NAVIGATE = false; + } - // set struct SemanticsNodeExtent - auto nodeEx = SetAndGetSemanticsNodeExtent(node); + /** 获取并分析每个语义节点的更新属性 */ + for (auto& item : update) { + // 获取当前更新的节点node + const flutter::SemanticsNode& node = item.second; + + // set struct SemanticsNodeExtent + auto nodeEx = SetAndGetSemanticsNodeExtent(node); + + //print semantics node and flags info for debugging + GetSemanticsNodeDebugInfo(node); + GetSemanticsFlagsDebugInfo(node); + + /** + * 构建flutter无障碍语义节点树 + * NOTE: 若使用g_flutterSemanticsTree.insert({node.id, node})方式 + * 来添加新增的语义节点会导致已有key值自动忽略,不会更新原有key对应的value + */ + g_flutterSemanticsTree[node.id] = node; + + // 获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 + int32_t childNodeCount = node.childrenInTraversalOrder.size(); + for (int32_t i = 0; i < childNodeCount; i++) { + g_parentChildIdVec.emplace_back( + std::make_pair(node.id, node.childrenInTraversalOrder[i])); + FML_DLOG(INFO) << "UpdateSemantics parentChildIdMap -> (" << node.id + << ", " << node.childrenInTraversalOrder[i] << ")"; + } - //print semantics node and flags info for debugging - GetSemanticsNodeDebugInfo(node); - GetSemanticsFlagsDebugInfo(node); + // 当滑动节点产生滑动,并执行滑动处理 + if (HasScrolled(node) && IsNodeVisible(node)) { + LOGD("UpdateSemantics -> has scrolled"); + if (OH_GetSdkApiVersion() >= 13) { + ArkUI_AccessibilityElementInfo* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = + OhosAccessibilityDDL::DLLoadCreateElemInfoFunc("OH_ArkUI_CreateAccessibilityElementInfo"); + if (OH_ArkUI_CreateAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_CreateAccessibilityElementInfo is null, %{public}s", dlerror()); + } + ArkUI_AccessibilityElementInfo* _elementInfo = + OH_ArkUI_CreateAccessibilityElementInfo(); + + FlutterNodeToElementInfoById(_elementInfo, static_cast(node.id)); + FlutterScrollExecution(node, _elementInfo); + + void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = + OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); + if (OH_ArkUI_DestoryAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_DestoryAccessibilityElementInfo is null, %{public}s", dlerror()); + } + OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); + _elementInfo = nullptr; + } + } - /** - * 构建flutter无障碍语义节点树 - * NOTE: 若使用g_flutterSemanticsTree.insert({node.id, node})方式 - * 来添加新增的语义节点会导致已有key值自动忽略,不会更新原有key对应的value - */ - g_flutterSemanticsTree[node.id] = node; + // 判断是否触发liveRegion活动区,当前节点是否活跃 + if (node.HasFlag(FLAGS_::kIsLiveRegion)) { + FML_DLOG(INFO) + << "UpdateSemantics -> LiveRegion, node.id=" << node.id; + FlutterPageUpdate(ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); + } + } - // 获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 - int32_t childNodeCount = node.childrenInTraversalOrder.size(); - for (int32_t i = 0; i < childNodeCount; i++) { - g_parentChildIdVec.emplace_back( - std::make_pair(node.id, node.childrenInTraversalOrder[i])); - FML_DLOG(INFO) << "UpdateSemantics parentChildIdMap -> (" << node.id - << ", " << node.childrenInTraversalOrder[i] << ")"; + // 遍历更新的actions,并将所有的actions的id添加进actionMap + for (const auto& item : actions) { + const flutter::CustomAccessibilityAction action = item.second; + GetCustomActionDebugInfo(action); + g_actions_mp[action.id] = action; } - - // 当滑动节点产生滑动,并执行滑动处理 - if (HasScrolled(node) && IsNodeVisible(node)) { - ArkUI_AccessibilityElementInfo* _elementInfo = - OH_ArkUI_CreateAccessibilityElementInfo(); - - FlutterNodeToElementInfoById(_elementInfo, static_cast(node.id)); - FlutterScrollExecution(node, _elementInfo); - - OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); - _elementInfo = nullptr; + // 打印flutter语义树的不同节点的属性信息 + for (const auto& item : g_flutterSemanticsTree) { + FML_DLOG(INFO) << "g_flutterSemanticsTree -> {" << item.first << ", " + << item.second.id << "}"; } - - // 判断是否触发liveRegion活动区,当前节点是否活跃 - if (node.HasFlag(FLAGS_::kIsLiveRegion)) { - FML_DLOG(INFO) - << "UpdateSemantics -> LiveRegion, node.id=" << node.id; - FlutterPageUpdate(ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); + for (const auto& item : g_parentChildIdVec) { + FML_DLOG(INFO) << "g_parentChildIdVec -> (" << item.first << ", " + << item.second << ")"; + } + //打印按层次遍历排序的flutter语义树节点id数组 + std::vector levelOrderTraversalTree = GetLevelOrderTraversalTree(0); + for (const auto& item: levelOrderTraversalTree) { + FML_DLOG(INFO) << "LevelOrderTraversalTree: { " << item << " }"; } - } - - // 遍历更新的actions,并将所有的actions的id添加进actionMap - for (const auto& item : actions) { - const flutter::CustomAccessibilityAction action = item.second; - GetCustomActionDebugInfo(action); - g_actions_mp[action.id] = action; - } - - // 打印flutter语义树的不同节点的属性信息 - for (const auto& item : g_flutterSemanticsTree) { - FML_DLOG(INFO) << "g_flutterSemanticsTree -> {" << item.first << ", " - << item.second.id << "}"; - } - for (const auto& item : g_parentChildIdVec) { - FML_DLOG(INFO) << "g_parentChildIdVec -> (" << item.first << ", " - << item.second << ")"; - } - - //打印按层次遍历排序的flutter语义树节点id数组 - std::vector levelOrderTraversalTree = GetLevelOrderTraversalTree(0); - for (const auto& item: levelOrderTraversalTree) { - FML_DLOG(INFO) << "LevelOrderTraversalTree: { " << item << " }"; - } - FML_DLOG(INFO) << "=== UpdateSemantics is end ==="; + FML_DLOG(INFO) << "=== UpdateSemantics is end ==="; } /** @@ -175,76 +189,87 @@ void OhosAccessibilityBridge::FlutterScrollExecution( flutter::SemanticsNode node, ArkUI_AccessibilityElementInfo* elementInfoFromList) { - double nodePosition = node.scrollPosition; - double nodeScrollExtentMax = node.scrollExtentMax; - double nodeScrollExtentMin = node.scrollExtentMin; - double infinity = std::numeric_limits::infinity(); - - // 设置flutter可滑动的最大范围值 - if (nodeScrollExtentMax == infinity) { - nodeScrollExtentMax = SCROLL_EXTENT_FOR_INFINITY; - if (nodePosition > SCROLL_POSITION_CAP_FOR_INFINITY) { - nodePosition = SCROLL_POSITION_CAP_FOR_INFINITY; + double nodePosition = node.scrollPosition; + double nodeScrollExtentMax = node.scrollExtentMax; + double nodeScrollExtentMin = node.scrollExtentMin; + double infinity = std::numeric_limits::infinity(); + + // 设置flutter可滑动的最大范围值 + if (nodeScrollExtentMax == infinity) { + nodeScrollExtentMax = SCROLL_EXTENT_FOR_INFINITY; + if (nodePosition > SCROLL_POSITION_CAP_FOR_INFINITY) { + nodePosition = SCROLL_POSITION_CAP_FOR_INFINITY; + } } - } - if (nodeScrollExtentMin == infinity) { - nodeScrollExtentMax += SCROLL_EXTENT_FOR_INFINITY; - if (nodePosition < -SCROLL_POSITION_CAP_FOR_INFINITY) { - nodePosition = -SCROLL_POSITION_CAP_FOR_INFINITY; + if (nodeScrollExtentMin == infinity) { + nodeScrollExtentMax += SCROLL_EXTENT_FOR_INFINITY; + if (nodePosition < -SCROLL_POSITION_CAP_FOR_INFINITY) { + nodePosition = -SCROLL_POSITION_CAP_FOR_INFINITY; + } + nodePosition += SCROLL_EXTENT_FOR_INFINITY; + } else { + nodeScrollExtentMax -= node.scrollExtentMin; + nodePosition -= node.scrollExtentMin; } - nodePosition += SCROLL_EXTENT_FOR_INFINITY; - } else { - nodeScrollExtentMax -= node.scrollExtentMin; - nodePosition -= node.scrollExtentMin; - } - if (node.HasAction(ACTIONS_::kScrollUp) || - node.HasAction(ACTIONS_::kScrollDown)) { - } else if (node.HasAction(ACTIONS_::kScrollLeft) || - node.HasAction(ACTIONS_::kScrollRight)) { - } + if (node.HasAction(ACTIONS_::kScrollUp) || + node.HasAction(ACTIONS_::kScrollDown)) { + } else if (node.HasAction(ACTIONS_::kScrollLeft) || + node.HasAction(ACTIONS_::kScrollRight)) { + } // 当可滑动组件存在滑动子节点 if (node.scrollChildren > 0) { // 配置当前滑动组件的子节点总数 int32_t itemCount = node.scrollChildren; - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetItemCount( - elementInfoFromList, itemCount) - ); - // 设置当前页面可见的起始滑动index - int32_t startItemIndex = node.scrollIndex; - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, - startItemIndex) - ); - - // 计算当前滑动位置页面的可见子滑动节点数量 - int visibleChildren = 0; - // handle hidden children at the beginning and end of the list. - for (const auto& childId : node.childrenInHitTestOrder) { - auto childNode = GetFlutterSemanticsNode(childId); - if (!childNode.HasFlag(FLAGS_::kIsHidden)) { - visibleChildren += 1; - } - } - // 当可见滑动子节点数量超过滑动组件总子节点数量 - if (node.scrollIndex + visibleChildren > node.scrollChildren) { - FML_DLOG(WARNING) - << "FlutterScrollExecution -> Scroll index is out of bounds"; - } - // 当滑动击中子节点数量为0 - if (!node.childrenInHitTestOrder.size()) { - FML_DLOG(WARNING) << "FlutterScrollExecution -> Had scrollChildren but no " - "childrenInHitTestOrder"; - } - // 设置当前页面可见的末尾滑动index - int32_t endItemIndex = node.scrollIndex + visibleChildren - 1; - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetEndItemIndex(elementInfoFromList, - endItemIndex) - ); + if (OH_GetSdkApiVersion() >= 13) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetItemCount)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetItemCount"); + if (OH_ArkUI_AccessibilityElementInfoSetItemCount == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetItemCount is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetItemCount(elementInfoFromList, itemCount)); + + // 设置当前页面可见的起始滑动index + int32_t startItemIndex = node.scrollIndex; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetStartItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetStartItemIndex"); + if (OH_ArkUI_AccessibilityElementInfoSetStartItemIndex == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetStartItemIndex is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, startItemIndex)); + + // 计算当前滑动位置页面的可见子滑动节点数量 + int visibleChildren = 0; + // handle hidden children at the beginning and end of the list. + for (const auto& childId : node.childrenInHitTestOrder) { + auto childNode = GetFlutterSemanticsNode(childId); + if (!childNode.HasFlag(FLAGS_::kIsHidden)) { + visibleChildren += 1; + } + } + // 当可见滑动子节点数量超过滑动组件总子节点数量 + if (node.scrollIndex + visibleChildren > node.scrollChildren) { + FML_DLOG(WARNING) + << "FlutterScrollExecution -> Scroll index is out of bounds"; + } + // 当滑动击中子节点数量为0 + if (!node.childrenInHitTestOrder.size()) { + FML_DLOG(WARNING) << "FlutterScrollExecution -> Had scrollChildren but no " + "childrenInHitTestOrder"; + } + // 设置当前页面可见的末尾滑动index + int32_t endItemIndex = node.scrollIndex + visibleChildren - 1; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEndItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetEndItemIndex"); + if (OH_ArkUI_AccessibilityElementInfoSetEndItemIndex == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetEndItemIndex is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetEndItemIndex(elementInfoFromList, endItemIndex) + ); + } } } @@ -255,26 +280,47 @@ void OhosAccessibilityBridge::FlutterScrollExecution( void OhosAccessibilityBridge::FlutterPageUpdate( ArkUI_AccessibilityEventType eventType) { - if (provider_ == nullptr) { - FML_DLOG(ERROR) << "PageStateUpdate ->" - "AccessibilityProvider = nullptr"; - return; - } - ArkUI_AccessibilityEventInfo* pageUpdateEventInfo = - OH_ArkUI_CreateAccessibilityEventInfo(); - - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityEventSetEventType(pageUpdateEventInfo, eventType) - ); - - auto callback = [](int32_t errorCode) { - FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; - }; - - OH_ArkUI_SendAccessibilityAsyncEvent(provider_, pageUpdateEventInfo, - callback); - OH_ArkUI_DestoryAccessibilityEventInfo(pageUpdateEventInfo); - pageUpdateEventInfo = nullptr; + if (provider_ == nullptr) { + FML_DLOG(ERROR) << "PageStateUpdate ->" + "AccessibilityProvider = nullptr"; + return; + } + if (OH_GetSdkApiVersion() >= 13) { + ArkUI_AccessibilityEventInfo* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = + OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); + if (OH_ArkUI_CreateAccessibilityEventInfo == nullptr) { + LOGE("OH_ArkUI_CreateAccessibilityEventInfo is null, %{public}s", dlerror()); + } + ArkUI_AccessibilityEventInfo* pageUpdateEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); + + int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = + OhosAccessibilityDDL::DLLoadSetEventFunc("OH_ArkUI_AccessibilityEventSetEventType"); + if (OH_ArkUI_AccessibilityEventSetEventType == nullptr) { + LOGE("OH_ArkUI_AccessibilityEventSetEventType is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetEventType(pageUpdateEventInfo, eventType) + ); + + auto callback = [](int32_t errorCode) { + FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; + }; + + void (*OH_ArkUI_SendAccessibilityAsyncEvent)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*callback)(int32_t)) = + OhosAccessibilityDDL::DLLoadSendAsyncEventFunc("OH_ArkUI_SendAccessibilityAsyncEvent"); + if (OH_ArkUI_SendAccessibilityAsyncEvent == nullptr) { + LOGE("OH_ArkUI_SendAccessibilityAsyncEvent is null, %{public}s", dlerror()); + } + OH_ArkUI_SendAccessibilityAsyncEvent(provider_, pageUpdateEventInfo, callback); + + void (*OH_ArkUI_DestoryAccessibilityEventInfo)(ArkUI_AccessibilityEventInfo*) = + OhosAccessibilityDDL::DLLoadDestroyEventFunc("OH_ArkUI_DestoryAccessibilityEventInfo"); + if (OH_ArkUI_DestoryAccessibilityEventInfo == nullptr) { + LOGE("OH_ArkUI_DestoryAccessibilityEventInfo is null, %{public}s", dlerror()); + } + OH_ArkUI_DestoryAccessibilityEventInfo(pageUpdateEventInfo); + pageUpdateEventInfo = nullptr; + } } /** @@ -282,41 +328,85 @@ void OhosAccessibilityBridge::FlutterPageUpdate( */ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() { - if (provider_ == nullptr) { - FML_DLOG(ERROR) << "RequestFocusWhenPageUpdate ->" - "AccessibilityProvider = nullptr"; - return; - } - ArkUI_AccessibilityEventInfo* reqFocusEventInfo = - OH_ArkUI_CreateAccessibilityEventInfo(); - ArkUI_AccessibilityElementInfo* elementInfo = - OH_ArkUI_CreateAccessibilityElementInfo(); - - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityEventSetEventType( - reqFocusEventInfo, - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_REQUEST_ACCESSIBILITY_FOCUS) - ); - - int32_t requestFocusId = 0; - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityEventSetRequestFocusId(reqFocusEventInfo, - requestFocusId) - ); - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityEventSetElementInfo(reqFocusEventInfo, elementInfo) - ); - - auto callback = [](int32_t errorCode) { - FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; - }; - OH_ArkUI_SendAccessibilityAsyncEvent(provider_, reqFocusEventInfo, callback); - - OH_ArkUI_DestoryAccessibilityEventInfo(reqFocusEventInfo); - reqFocusEventInfo = nullptr; - OH_ArkUI_DestoryAccessibilityElementInfo(elementInfo); - elementInfo = nullptr; + if (provider_ == nullptr) { + FML_DLOG(ERROR) << "RequestFocusWhenPageUpdate ->" + "AccessibilityProvider = nullptr"; + return; + } + if (OH_GetSdkApiVersion() >= 13) { + ArkUI_AccessibilityEventInfo* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = + OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); + if (OH_ArkUI_CreateAccessibilityEventInfo == nullptr) { + LOGE("OH_ArkUI_CreateAccessibilityEventInfo is null, %{public}s", dlerror()); + } + ArkUI_AccessibilityEventInfo* reqFocusEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); + + ArkUI_AccessibilityElementInfo* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = + OhosAccessibilityDDL::DLLoadCreateElemInfoFunc("OH_ArkUI_CreateAccessibilityElementInfo"); + if (OH_ArkUI_CreateAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_CreateAccessibilityElementInfo is null, %{public}s", dlerror()); + } + ArkUI_AccessibilityElementInfo* elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); + + int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = + OhosAccessibilityDDL::DLLoadSetEventFunc("OH_ArkUI_AccessibilityEventSetEventType"); + if (OH_ArkUI_AccessibilityEventSetEventType == nullptr) { + LOGE("OH_ArkUI_AccessibilityEventSetEventType is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetEventType( + reqFocusEventInfo, + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_REQUEST_ACCESSIBILITY_FOCUS) + ); + + int32_t requestFocusId = 0; + int32_t (*OH_ArkUI_AccessibilityEventSetRequestFocusId)(ArkUI_AccessibilityEventInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetReqFocusFunc("OH_ArkUI_AccessibilityEventSetRequestFocusId"); + if (OH_ArkUI_AccessibilityEventSetRequestFocusId == nullptr) { + LOGE("OH_ArkUI_AccessibilityEventSetRequestFocusId is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetRequestFocusId(reqFocusEventInfo, + requestFocusId) + ); + + int32_t (*OH_ArkUI_AccessibilityEventSetElementInfo)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityElementInfo*) = + OhosAccessibilityDDL::DLLoadSetEventElemFunc("OH_ArkUI_AccessibilityEventSetElementInfo"); + if (OH_ArkUI_AccessibilityEventSetElementInfo == nullptr) { + LOGE("OH_ArkUI_AccessibilityEventSetElementInfo is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetElementInfo(reqFocusEventInfo, elementInfo) + ); + + auto callback = [](int32_t errorCode) { + FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; + }; + + void (*OH_ArkUI_SendAccessibilityAsyncEvent)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*callback)(int32_t)) = + OhosAccessibilityDDL::DLLoadSendAsyncEventFunc("OH_ArkUI_SendAccessibilityAsyncEvent"); + if (OH_ArkUI_SendAccessibilityAsyncEvent == nullptr) { + LOGE("OH_ArkUI_SendAccessibilityAsyncEvent is null, %{public}s", dlerror()); + } + OH_ArkUI_SendAccessibilityAsyncEvent(provider_, reqFocusEventInfo, callback); + + void (*OH_ArkUI_DestoryAccessibilityEventInfo)(ArkUI_AccessibilityEventInfo*) = + OhosAccessibilityDDL::DLLoadDestroyEventFunc("OH_ArkUI_DestoryAccessibilityEventInfo"); + if (OH_ArkUI_DestoryAccessibilityEventInfo == nullptr) { + LOGE("OH_ArkUI_DestoryAccessibilityEventInfo is null, %{public}s", dlerror()); + } + OH_ArkUI_DestoryAccessibilityEventInfo(reqFocusEventInfo); + reqFocusEventInfo = nullptr; + + void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = + OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); + if (OH_ArkUI_DestoryAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_DestoryAccessibilityElementInfo is null, %{public}s", dlerror()); + } + OH_ArkUI_DestoryAccessibilityElementInfo(elementInfo); + elementInfo = nullptr; + } } /** @@ -324,53 +414,78 @@ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() */ void OhosAccessibilityBridge::Announce(std::unique_ptr& message) { - if (provider_ == nullptr) { - FML_DLOG(ERROR) << "announce ->" - "AccessibilityProvider = nullptr"; - return; - } - // 创建并设置屏幕朗读事件 - ArkUI_AccessibilityEventInfo* announceEventInfo = - OH_ArkUI_CreateAccessibilityEventInfo(); - - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityEventSetEventType( - announceEventInfo, - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ANNOUNCE_FOR_ACCESSIBILITY) - ); - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility( - announceEventInfo, message.get()) - ); - FML_DLOG(INFO) << ("announce -> message: ") - << (message.get()); - - auto callback = [](int32_t errorCode) { - FML_DLOG(WARNING) << "announce callback-> errorCode =" << errorCode; - }; - OH_ArkUI_SendAccessibilityAsyncEvent(provider_, announceEventInfo, callback); - - OH_ArkUI_DestoryAccessibilityEventInfo(announceEventInfo); - announceEventInfo = nullptr; - - return; + if (provider_ == nullptr) { + FML_DLOG(ERROR) << "announce ->" + "AccessibilityProvider = nullptr"; + return; + } + if (OH_GetSdkApiVersion() >= 13) { + // 创建并设置屏幕朗读事件 + ArkUI_AccessibilityEventInfo* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = + OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); + if (OH_ArkUI_CreateAccessibilityEventInfo == nullptr) { + LOGE("OH_ArkUI_CreateAccessibilityEventInfo is null, %{public}s", dlerror()); + } + ArkUI_AccessibilityEventInfo* announceEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); + + + int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = + OhosAccessibilityDDL::DLLoadSetEventFunc("OH_ArkUI_AccessibilityEventSetEventType"); + if (OH_ArkUI_AccessibilityEventSetEventType == nullptr) { + LOGE("OH_ArkUI_AccessibilityEventSetEventType is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetEventType( + announceEventInfo, + ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ANNOUNCE_FOR_ACCESSIBILITY) + ); + + int32_t (*OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility)(ArkUI_AccessibilityEventInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetEventStringFunc("OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility"); + if (OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility == nullptr) { + LOGE("OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility( + announceEventInfo, message.get()) + ); + FML_DLOG(INFO) << ("announce -> message: ") << (message.get()); + + auto callback = [](int32_t errorCode) { + FML_DLOG(WARNING) << "announce callback-> errorCode =" << errorCode; + }; + + void (*OH_ArkUI_SendAccessibilityAsyncEvent)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*callback)(int32_t)) = + OhosAccessibilityDDL::DLLoadSendAsyncEventFunc("OH_ArkUI_SendAccessibilityAsyncEvent"); + if (OH_ArkUI_SendAccessibilityAsyncEvent == nullptr) { + LOGE("OH_ArkUI_SendAccessibilityAsyncEvent is null, %{public}s", dlerror()); + } + OH_ArkUI_SendAccessibilityAsyncEvent(provider_, announceEventInfo, callback); + + void (*OH_ArkUI_DestoryAccessibilityEventInfo)(ArkUI_AccessibilityEventInfo*) = + OhosAccessibilityDDL::DLLoadDestroyEventFunc("OH_ArkUI_DestoryAccessibilityEventInfo"); + if (OH_ArkUI_DestoryAccessibilityEventInfo == nullptr) { + LOGE("OH_ArkUI_DestoryAccessibilityEventInfo is null, %{public}s", dlerror()); + } + OH_ArkUI_DestoryAccessibilityEventInfo(announceEventInfo); + announceEventInfo = nullptr; + } } //获取根节点 flutter::SemanticsNode OhosAccessibilityBridge::GetFlutterRootSemanticsNode() { - if (!g_flutterSemanticsTree.size()) { - FML_DLOG(ERROR) - << "GetFlutterRootSemanticsNode -> g_flutterSemanticsTree.size()=0"; - return {}; - } - if (g_flutterSemanticsTree.find(0) == g_flutterSemanticsTree.end()) { - FML_DLOG(ERROR) << "GetFlutterRootSemanticsNode -> g_flutterSemanticsTree " - "has no keys = 0"; - return {}; - } - return g_flutterSemanticsTree.at(0); + if (!g_flutterSemanticsTree.size()) { + FML_DLOG(ERROR) + << "GetFlutterRootSemanticsNode -> g_flutterSemanticsTree.size()=0"; + return {}; + } + if (g_flutterSemanticsTree.find(0) == g_flutterSemanticsTree.end()) { + FML_DLOG(ERROR) << "GetFlutterRootSemanticsNode -> g_flutterSemanticsTree " + "has no keys = 0"; + return {}; + } + return g_flutterSemanticsTree.at(0); } /** @@ -401,94 +516,171 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( "g_flutterSemanticsTree.size() = 0"; return; } - // 将flutter语义节点树传递给arkui的无障碍elementinfo - for (const auto& item : g_flutterSemanticsTree) { - flutter::SemanticsNode flutterNode = item.second; - - // 创建elementinfo,系统自动加入到elementinfolist - ArkUI_AccessibilityElementInfo* elementInfo = - OH_ArkUI_AddAndGetAccessibilityElementInfo(elementInfoList); - if (elementInfo == nullptr) { - FML_DLOG(INFO) << "OhosAccessibilityBridge::FlutterTreeToArkuiTree " - "elementInfo is null"; - return; - } - // 设置elementinfo的屏幕坐标范围 - int32_t left = static_cast(flutterNode.rect.fLeft); - int32_t top = static_cast(flutterNode.rect.fTop); - int32_t right = static_cast(flutterNode.rect.fRight); - int32_t bottom = static_cast(flutterNode.rect.fBottom); - ArkUI_AccessibleRect rect = {left, top, right, bottom}; - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfo, &rect) - ); - - // 设置elementinfo的action类型 - std::string widget_type = GetNodeComponentType(flutterNode); - FlutterSetElementInfoOperationActions(elementInfo, widget_type); - - // 设置elementid - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfo, flutterNode.id) - ); - - // 设置父节点id - int32_t parentId = GetParentId(flutterNode.id); - if (flutterNode.id == 0) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, ARKUI_ACCESSIBILITY_ROOT_PARENT_ID) - ); - } else { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, parentId) - ); - } - - // 设置孩子节点 - int32_t childCount = flutterNode.childrenInTraversalOrder.size(); - auto childrenIdsVec = flutterNode.childrenInTraversalOrder; - std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); - int64_t childNodeIds[childCount]; - for (int32_t i = 0; i < childCount; i++) { - childNodeIds[i] = static_cast(childrenIdsVec[i]); - FML_DLOG(INFO) << "FlutterTreeToArkuiTree flutterNode.id= " - << flutterNode.id << " childCount= " << childCount - << " childNodeId=" << childNodeIds[i]; - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfo, - childCount, - childNodeIds) - ); - - // 配置常用属性,force to true for debugging - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfo, true)); - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfo, true)); - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfo, true)); - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfo, true)); - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfo, true)); - - // 设置组件类型 - std::string componentTypeName = GetNodeComponentType(flutterNode); - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetComponentType( - elementInfo, componentTypeName.c_str()) - ); - - std::string contents = componentTypeName + "_content"; - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetContents(elementInfo, contents.c_str()) - ); - - // 设置无障碍相关属性 - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( - elementInfo, flutterNode.label.c_str()) - ); - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfo, "yes")); - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfo, false)); + if (OH_GetSdkApiVersion() >= 13) { + // 将flutter语义节点树传递给arkui的无障碍elementinfo + for (const auto& item : g_flutterSemanticsTree) { + flutter::SemanticsNode flutterNode = item.second; + + // 创建elementinfo,系统自动加入到elementinfolist + ArkUI_AccessibilityElementInfo* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = + OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); + if (OH_ArkUI_AddAndGetAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_AddAndGetAccessibilityElementInfo is null, %{public}s", dlerror()); + } + ArkUI_AccessibilityElementInfo* elementInfo = + OH_ArkUI_AddAndGetAccessibilityElementInfo(elementInfoList); + if (elementInfo == nullptr) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::FlutterTreeToArkuiTree " + "elementInfo is null"; + return; + } + // 设置elementinfo的屏幕坐标范围 + int32_t left = static_cast(flutterNode.rect.fLeft); + int32_t top = static_cast(flutterNode.rect.fTop); + int32_t right = static_cast(flutterNode.rect.fRight); + int32_t bottom = static_cast(flutterNode.rect.fBottom); + ArkUI_AccessibleRect rect = {left, top, right, bottom}; + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetScreenRect)(ArkUI_AccessibilityElementInfo*, ArkUI_AccessibleRect*) = + OhosAccessibilityDDL::DLLoadSetElemSreenRectFunc("OH_ArkUI_AccessibilityElementInfoSetScreenRect"); + if (OH_ArkUI_AccessibilityElementInfoSetScreenRect == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetScreenRect is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfo, &rect) + ); + + // 设置elementinfo的action类型 + std::string widget_type = GetNodeComponentType(flutterNode); + FlutterSetElementInfoOperationActions(elementInfo, widget_type); + + // 设置elementid + int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetElementId"); + if (OH_ArkUI_AccessibilityElementInfoSetElementId == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetElementId is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfo, flutterNode.id) + ); + + // 设置父节点id + int32_t parentId = GetParentId(flutterNode.id); + int32_t (*OH_ArkUI_AccessibilityElementInfoSetParentId)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetParentId"); + if (OH_ArkUI_AccessibilityElementInfoSetParentId == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetParentId is null, %{public}s", dlerror()); + } + if (flutterNode.id == 0) { + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, ARKUI_ACCESSIBILITY_ROOT_PARENT_ID) + ); + } else { + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, parentId)); + } + + // 设置孩子节点 + int32_t childCount = flutterNode.childrenInTraversalOrder.size(); + auto childrenIdsVec = flutterNode.childrenInTraversalOrder; + std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); + int64_t childNodeIds[childCount]; + for (int32_t i = 0; i < childCount; i++) { + childNodeIds[i] = static_cast(childrenIdsVec[i]); + FML_DLOG(INFO) << "FlutterTreeToArkuiTree flutterNode.id= " + << flutterNode.id << " childCount= " << childCount + << " childNodeId=" << childNodeIds[i]; + } + int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = + OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); + if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfo, childCount, childNodeIds) + ); + + // 配置常用属性,force to true for debugging + int32_t (*OH_ArkUI_AccessibilityElementInfoSetCheckable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetCheckable"); + if (OH_ArkUI_AccessibilityElementInfoSetCheckable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetCheckable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfo, true)); + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetFocusable"); + if (OH_ArkUI_AccessibilityElementInfoSetFocusable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetFocusable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfo, true)); + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetVisible)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetVisible"); + if (OH_ArkUI_AccessibilityElementInfoSetVisible == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetVisible is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfo, true)); + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); + if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfo, true)); + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); + if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfo, true)); + + // 设置组件类型 + std::string componentTypeName = GetNodeComponentType(flutterNode); + int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetComponentType"); + if (OH_ArkUI_AccessibilityElementInfoSetComponentType == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetComponentType is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfo, componentTypeName.c_str()) + ); + + std::string contents = componentTypeName + "_content"; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetContents)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetContents"); + if (OH_ArkUI_AccessibilityElementInfoSetContents == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetContents is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetContents(elementInfo, contents.c_str()) + ); + + // 设置无障碍相关属性 + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityText)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText"); + if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityText == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfo, flutterNode.label.c_str()) + ); + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel"); + if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfo, "yes")); + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup"); + if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfo, false)); + } } - FML_DLOG(INFO) << "FlutterTreeToArkuiTree is end"; } /** @@ -496,21 +688,20 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( */ int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) { - if (!g_parentChildIdVec.size()) { - FML_DLOG(INFO) - << "OhosAccessibilityBridge::GetParentId parentChildIdMap.size()=0"; - return ARKUI_ACCESSIBILITY_ROOT_PARENT_ID; - } - if (elementId == -1) { - return ARKUI_ACCESSIBILITY_ROOT_PARENT_ID; - } - int32_t childElementId = static_cast(elementId); - for (const auto& item : g_parentChildIdVec) { - if (item.second == childElementId) { - return item.first; + if (!g_parentChildIdVec.size()) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::GetParentId parentChildIdMap.size()=0"; + return ARKUI_ACCESSIBILITY_ROOT_PARENT_ID; } - } - return RET_ERROR_STATE_CODE; + if (elementId == -1) { + return ARKUI_ACCESSIBILITY_ROOT_PARENT_ID; + } + int32_t childElementId = static_cast(elementId); + for (const auto& item : g_parentChildIdVec) { + if (item.second == childElementId) { + return item.first; + } + } + return RET_ERROR_STATE_CODE; } /** @@ -522,23 +713,23 @@ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, float right, float bottom) { - g_screenRectMap[flutterNodeId] = - std::make_pair(std::make_pair(left, top), std::make_pair(right, bottom)); - FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId - << ", <" << left << ", " << top << ", " << right << ", " - << bottom << "> } is succeed"; + g_screenRectMap[flutterNodeId] = + std::make_pair(std::make_pair(left, top), std::make_pair(right, bottom)); + FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId + << ", <" << left << ", " << top << ", " << right << ", " + << bottom << "> } is succeed"; } std::pair, std::pair> OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) { - if (!g_screenRectMap.empty() && g_screenRectMap.count(flutterNodeId) > 0) { - return g_screenRectMap.at(flutterNodeId); - } else { - FML_DLOG(ERROR) << "GetAbsoluteScreenRect -> flutterNodeId=" - << flutterNodeId << " is not found !"; - return {}; - } + if (!g_screenRectMap.empty() && g_screenRectMap.count(flutterNodeId) > 0) { + return g_screenRectMap.at(flutterNodeId); + } else { + FML_DLOG(ERROR) << "GetAbsoluteScreenRect -> flutterNodeId=" + << flutterNodeId << " is not found !"; + return {}; + } } /** @@ -548,98 +739,97 @@ OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( flutter::SemanticsNode currNode) { - // 获取当前flutter节点的相对rect - auto currLeft = static_cast(currNode.rect.fLeft); - auto currTop = static_cast(currNode.rect.fTop); - auto currRight = static_cast(currNode.rect.fRight); - auto currBottom = static_cast(currNode.rect.fBottom); - - // 获取当前flutter节点的缩放、平移、透视等矩阵坐标转换 - SkMatrix transform = currNode.transform.asM33(); - auto _kMScaleX = transform.get(SkMatrix::kMScaleX); - auto _kMTransX = transform.get(SkMatrix::kMTransX); - auto _kMScaleY = transform.get(SkMatrix::kMScaleY); - auto _kMTransY = transform.get(SkMatrix::kMTransY); - /** 以下矩阵坐标变换参数(如:旋转/错切、透视)场景目前暂不考虑 - * NOTE: SkMatrix::kMSkewX, SkMatrix::kMSkewY, - * SkMatrix::kMPersp0, SkMatrix::kMPersp1, SkMatrix::kMPersp2 - */ - - // 获取当前flutter节点的父节点的相对rect - int32_t parentId = GetParentId(currNode.id); - auto parentNode = GetFlutterSemanticsNode(parentId); - auto parentRight = parentNode.rect.fRight; - auto parentBottom = parentNode.rect.fBottom; - - // 获取当前flutter节点的父节点的绝对坐标 - auto _rectPairs = GetAbsoluteScreenRect(parentNode.id); - auto realParentLeft = _rectPairs.first.first; - auto realParentTop = _rectPairs.first.second; - auto realParentRight = _rectPairs.second.first; - auto realParentBottom = _rectPairs.second.second; - - // 获取root节点的绝对坐标, 即xcomponent屏幕长宽 - auto _rootRect = GetAbsoluteScreenRect(0); - float rootWidth = _rootRect.second.first; - auto rootHeight = _rootRect.second.second; - - // 真实缩放系数 - float realScaleFactor = realParentRight / parentRight * 1.0; - float newLeft; - float newTop; - float newRight; - float newBottom; - - if (_kMScaleX > 1 && _kMScaleY > 1) { - // 子节点相对父节点进行变化(缩放、 平移) - newLeft = currLeft + _kMTransX * _kMScaleX; - newTop = currTop + _kMTransY * _kMScaleY; - newRight = currRight * _kMScaleX; - newBottom = currBottom * _kMScaleY; - // 更新当前flutter节点currNode的相对坐标 -> 屏幕绝对坐标 - SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); - } else { - // 若当前节点的相对坐标与父亲节点的相对坐标值相同,则直接继承坐标值 - if (currRight == parentRight && currBottom == parentBottom) { - newLeft = realParentLeft; - newTop = realParentTop; - newRight = realParentRight; - newBottom = realParentBottom; - } else { - // 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 - newLeft = (currLeft + _kMTransX) * realScaleFactor + realParentLeft; - newTop = (currTop + _kMTransY) * realScaleFactor + realParentTop; - newRight = - (currLeft + _kMTransX + currRight) * realScaleFactor + realParentLeft; - newBottom = - (currTop + _kMTransY + currBottom) * realScaleFactor + realParentTop; - } - // 若子节点rect超过父节点则跳过显示(单个屏幕显示不下,滑动再重新显示) - const bool IS_OVER_SCREEN_AREA = newLeft < realParentLeft || - newTop < realParentTop || - newRight > realParentRight || - newBottom > realParentBottom || - newLeft >= newRight || - newTop >= newBottom; - if (IS_OVER_SCREEN_AREA) { - FML_DLOG(ERROR) << "ConvertChildRelativeRectToScreenRect childRect is " - "bigger than parentRect -> { nodeId: " - << currNode.id << ", (" << newLeft << ", " << newTop - << ", " << newRight << ", " << newBottom << ")}"; - // 防止滑动场景下绿框坐标超出屏幕范围,进行正则化处理 - newLeft = static_cast(newLeft) % static_cast(rootWidth); - newTop = static_cast(newTop) % static_cast(rootHeight); - newRight = static_cast(newRight) % static_cast(rootWidth); - newBottom = static_cast(newBottom) % static_cast(rootHeight); - SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, - newBottom); + // 获取当前flutter节点的相对rect + auto currLeft = static_cast(currNode.rect.fLeft); + auto currTop = static_cast(currNode.rect.fTop); + auto currRight = static_cast(currNode.rect.fRight); + auto currBottom = static_cast(currNode.rect.fBottom); + + // 获取当前flutter节点的缩放、平移、透视等矩阵坐标转换 + SkMatrix transform = currNode.transform.asM33(); + auto _kMScaleX = transform.get(SkMatrix::kMScaleX); + auto _kMTransX = transform.get(SkMatrix::kMTransX); + auto _kMScaleY = transform.get(SkMatrix::kMScaleY); + auto _kMTransY = transform.get(SkMatrix::kMTransY); + /** 以下矩阵坐标变换参数(如:旋转/错切、透视)场景目前暂不考虑 + * NOTE: SkMatrix::kMSkewX, SkMatrix::kMSkewY, + * SkMatrix::kMPersp0, SkMatrix::kMPersp1, SkMatrix::kMPersp2 + */ + + // 获取当前flutter节点的父节点的相对rect + int32_t parentId = GetParentId(currNode.id); + auto parentNode = GetFlutterSemanticsNode(parentId); + auto parentRight = parentNode.rect.fRight; + auto parentBottom = parentNode.rect.fBottom; + + // 获取当前flutter节点的父节点的绝对坐标 + auto _rectPairs = GetAbsoluteScreenRect(parentNode.id); + auto realParentLeft = _rectPairs.first.first; + auto realParentTop = _rectPairs.first.second; + auto realParentRight = _rectPairs.second.first; + auto realParentBottom = _rectPairs.second.second; + + // 获取root节点的绝对坐标, 即xcomponent屏幕长宽 + auto _rootRect = GetAbsoluteScreenRect(0); + // float rootWidth = _rootRect.second.first; + auto rootHeight = _rootRect.second.second; + + // 真实缩放系数 + float realScaleFactor = realParentRight / parentRight * 1.0; + float newLeft; + float newTop; + float newRight; + float newBottom; + + if (_kMScaleX > 1 && _kMScaleY > 1) { + // 子节点相对父节点进行变化(缩放、 平移) + newLeft = currLeft + _kMTransX * _kMScaleX; + newTop = currTop + _kMTransY * _kMScaleY; + newRight = currRight * _kMScaleX; + newBottom = currBottom * _kMScaleY; + // 更新当前flutter节点currNode的相对坐标 -> 屏幕绝对坐标 + SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); } else { - SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); + // 若当前节点的相对坐标与父亲节点的相对坐标值相同,则直接继承坐标值 + if (currRight == parentRight && currBottom == parentBottom) { + newLeft = realParentLeft; + newTop = realParentTop; + newRight = realParentRight; + newBottom = realParentBottom; + } else { + // 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 + newLeft = (currLeft + _kMTransX) * realScaleFactor + realParentLeft; + newTop = (currTop + _kMTransY) * realScaleFactor + realParentTop; + newRight = + (currLeft + _kMTransX + currRight) * realScaleFactor + realParentLeft; + newBottom = + (currTop + _kMTransY + currBottom) * realScaleFactor + realParentTop; + } + // 若子节点rect超过父节点则跳过显示(单个屏幕显示不下,滑动再重新显示) + const bool IS_OVER_SCREEN_AREA = newLeft < realParentLeft || + newTop < realParentTop || + newRight > realParentRight || + newBottom > realParentBottom || + newLeft >= newRight || + newTop >= newBottom; + if (IS_OVER_SCREEN_AREA) { + FML_DLOG(ERROR) << "ConvertChildRelativeRectToScreenRect childRect is " + "bigger than parentRect -> { nodeId: " + << currNode.id << ", (" << newLeft << ", " << newTop + << ", " << newRight << ", " << newBottom << ")}"; + // 防止滑动场景下绿框坐标超出屏幕范围,进行正则化处理 + // newLeft = static_cast(newLeft) % static_cast(rootWidth); + newTop = static_cast(newTop) % static_cast(rootHeight); + // newRight = static_cast(newRight) % static_cast(rootWidth); + newBottom = static_cast(newBottom) % static_cast(rootHeight); + SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); + } else { + SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); + } } - } - FML_DLOG(INFO) << "ConvertChildRelativeRectToScreenRect -> { nodeId: " - << currNode.id << ", (" << newLeft << ", " << newTop << ", " - << newRight << ", " << newBottom << ")}"; + FML_DLOG(INFO) << "ConvertChildRelativeRectToScreenRect -> { nodeId: " + << currNode.id << ", (" << newLeft << ", " << newTop << ", " + << newRight << ", " << newBottom << ")}"; } /** @@ -649,90 +839,157 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId) { - if (elementInfoFromList == nullptr) { - FML_DLOG(INFO) << "OhosAccessibilityBridge::FlutterNodeToElementInfoById " - "elementInfoFromList is null"; - return; - } - FML_DLOG(INFO) << "FlutterNodeToElementInfoById elementId = " << elementId; - // 当elementId = -1或0时,创建root节点 - if (elementId == 0 || elementId == -1) { - // 获取flutter的root节点 - flutter::SemanticsNode flutterNode = - GetFlutterSemanticsNode(static_cast(0)); - - // 设置elementinfo的屏幕坐标范围 - int32_t left = static_cast(flutterNode.rect.fLeft); - int32_t top = static_cast(flutterNode.rect.fTop); - int32_t right = static_cast(flutterNode.rect.fRight); - int32_t bottom = static_cast(flutterNode.rect.fBottom); - ArkUI_AccessibleRect rect = {left, top, right, bottom}; - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetScreenRect( - elementInfoFromList, &rect) - ); - - // 设置root节点的屏幕绝对坐标rect - SetAbsoluteScreenRect(0, left, top, right, bottom); - - // 设置elementinfo的action类型 - std::string widget_type = "root"; - FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); - - // 根据flutternode信息配置对应的elementinfo - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, 0) - ); - - // NOTE: arkui无障碍子系统强制设置root的父节点id = -2100000 (严禁更改) - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetParentId( - elementInfoFromList, ARKUI_ACCESSIBILITY_ROOT_PARENT_ID) - ); - - // 设置无障碍播报文本 - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( - elementInfoFromList, flutterNode.label.empty() ? flutterNode.hint.c_str() : flutterNode.label.c_str()) - ); - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel( - elementInfoFromList, "yes") - ); - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup( - elementInfoFromList, false) - ); - - // 配置child节点信息 - int32_t childCount = flutterNode.childrenInTraversalOrder.size(); - auto childrenIdsVec = flutterNode.childrenInTraversalOrder; - std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); - int64_t childNodeIds[childCount]; - for (int32_t i = 0; i < childCount; i++) { - childNodeIds[i] = static_cast(childrenIdsVec[i]); - FML_DLOG(INFO) - << "FlutterNodeToElementInfoById -> elementid=0 childCount=" - << childCount << " childNodeIds=" << childNodeIds[i]; - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetChildNodeIds( - elementInfoFromList, childCount, childNodeIds) - ); + if (elementInfoFromList == nullptr) { + FML_DLOG(INFO) << "OhosAccessibilityBridge::FlutterNodeToElementInfoById " + "elementInfoFromList is null"; + return; + } + FML_DLOG(INFO) << "FlutterNodeToElementInfoById elementId = " << elementId; - // 配置root节点常用属性 - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true)); - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true)); - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true)); - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true)); - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root")); - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, flutterNode.label.c_str())); - } else { - //当elementId >= 1时,根据flutter节点信息配置elementinfo无障碍属性 - FlutterSetElementInfoProperties(elementInfoFromList, elementId); - } - FML_DLOG(INFO) - << "=== OhosAccessibilityBridge::FlutterNodeToElementInfoById is end ==="; + if (OH_GetSdkApiVersion() >= 13) { + // 当elementId = -1或0时,创建root节点 + if (elementId == 0 || elementId == -1) { + // 获取flutter的root节点 + flutter::SemanticsNode flutterNode = + GetFlutterSemanticsNode(static_cast(0)); + + // 设置elementinfo的屏幕坐标范围 + int32_t left = static_cast(flutterNode.rect.fLeft); + int32_t top = static_cast(flutterNode.rect.fTop); + int32_t right = static_cast(flutterNode.rect.fRight); + int32_t bottom = static_cast(flutterNode.rect.fBottom); + ArkUI_AccessibleRect rect = {left, top, right, bottom}; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetScreenRect)(ArkUI_AccessibilityElementInfo*, ArkUI_AccessibleRect*) = + OhosAccessibilityDDL::DLLoadSetElemSreenRectFunc("OH_ArkUI_AccessibilityElementInfoSetScreenRect"); + if (OH_ArkUI_AccessibilityElementInfoSetScreenRect == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetScreenRect is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect) + ); + + // 设置root节点的屏幕绝对坐标rect + SetAbsoluteScreenRect(0, left, top, right, bottom); + + // 设置elementinfo的action类型 + std::string widget_type = "root"; + FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); + + // 根据flutternode信息配置对应的elementinfo + int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetElementId"); + if (OH_ArkUI_AccessibilityElementInfoSetElementId == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetElementId is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, 0)); + + // NOTE: arkui无障碍子系统强制设置root的父节点id = -2100000 (严禁更改) + int32_t (*OH_ArkUI_AccessibilityElementInfoSetParentId)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetParentId"); + if (OH_ArkUI_AccessibilityElementInfoSetParentId == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetParentId is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, ARKUI_ACCESSIBILITY_ROOT_PARENT_ID) + ); + + // 设置无障碍播报文本 + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityText)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText"); + if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityText == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( + elementInfoFromList, flutterNode.label.empty() ? flutterNode.hint.c_str() : flutterNode.label.c_str()) + ); + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel"); + if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes") + ); + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup"); + if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, false) + ); + + // 配置child节点信息 + int32_t childCount = flutterNode.childrenInTraversalOrder.size(); + auto childrenIdsVec = flutterNode.childrenInTraversalOrder; + std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); + int64_t childNodeIds[childCount]; + for (int32_t i = 0; i < childCount; i++) { + childNodeIds[i] = static_cast(childrenIdsVec[i]); + FML_DLOG(INFO) + << "FlutterNodeToElementInfoById -> elementid=0 childCount=" + << childCount << " childNodeIds=" << childNodeIds[i]; + } + int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = + OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); + if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds) + ); + + // 配置root节点常用属性 + int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetFocusable"); + if (OH_ArkUI_AccessibilityElementInfoSetFocusable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetFocusable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true)); + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetVisible)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetVisible"); + if (OH_ArkUI_AccessibilityElementInfoSetVisible == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetVisible is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true)); + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); + if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true)); + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); + if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true)); + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetComponentType"); + if (OH_ArkUI_AccessibilityElementInfoSetComponentType == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetComponentType is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root")); + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetContents)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetContents"); + if (OH_ArkUI_AccessibilityElementInfoSetContents == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetContents is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, flutterNode.label.c_str())); + } else { + //当elementId >= 1时,根据flutter节点信息配置elementinfo无障碍属性 + FlutterSetElementInfoProperties(elementInfoFromList, elementId); + } + } + FML_DLOG(INFO) << "=== OhosAccessibilityBridge::FlutterNodeToElementInfoById is end ==="; } /** @@ -751,106 +1008,110 @@ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( ArkUI_AccessibilityElementInfo* elementInfoFromList, std::string widget_type) { - if (widget_type == "textfield") { - // set elementinfo action types - int32_t actionTypeNum = 10; - ArkUI_AccessibleAction actions[actionTypeNum]; - - actions[0].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; - actions[0].description = "获取焦点"; - - actions[1].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; - actions[1].description = "清除焦点"; - - actions[2].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; - actions[2].description = "点击操作"; - - actions[3].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK; - actions[3].description = "长按操作"; - - actions[4].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY; - actions[4].description = "文本复制"; - - actions[5].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE; - actions[5].description = "文本粘贴"; - - actions[6].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT; - actions[6].description = "文本剪切"; - - actions[7].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT; - actions[7].description = "文本选择"; - - actions[8].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT; - actions[8].description = "文本内容设置"; - - actions[9].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION; - actions[9].description = "光标位置设置"; - - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetOperationActions( - elementInfoFromList, actionTypeNum, actions) - ); - } else if (widget_type == "scrollable") { - // if node is a scrollable component - int32_t actionTypeNum = 5; - ArkUI_AccessibleAction actions[actionTypeNum]; - - actions[0].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; - actions[0].description = "获取焦点"; - - actions[1].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; - actions[1].description = "清除焦点"; - - actions[2].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; - actions[2].description = "点击动作"; - - actions[3].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD; - actions[3].description = "向上滑动"; - - actions[4].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD; - actions[4].description = "向下滑动"; - - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetOperationActions( - elementInfoFromList, actionTypeNum, actions) - ); - } else { - // set common component action types - int32_t actionTypeNum = 3; - ArkUI_AccessibleAction actions[actionTypeNum]; - - actions[0].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; - actions[0].description = "获取焦点"; - - actions[1].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; - actions[1].description = "清除焦点"; - - actions[2].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; - actions[2].description = "点击动作"; - - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetOperationActions( - elementInfoFromList, actionTypeNum, actions) - ); - } + if (OH_GetSdkApiVersion() >= 13) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetOperationActions)(ArkUI_AccessibilityElementInfo*, int32_t, ArkUI_AccessibleAction*) = + OhosAccessibilityDDL::DLLoadSetElemOperActionsFunc("OH_ArkUI_AccessibilityElementInfoSetOperationActions"); + if (OH_ArkUI_AccessibilityElementInfoSetOperationActions == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetOperationActions is null, %{public}s", dlerror()); + } + if (widget_type == "textfield") { + // set elementinfo action types + int32_t actionTypeNum = 10; + ArkUI_AccessibleAction actions[actionTypeNum]; + + actions[0].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; + actions[0].description = "获取焦点"; + + actions[1].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].description = "清除焦点"; + + actions[2].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; + actions[2].description = "点击操作"; + + actions[3].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK; + actions[3].description = "长按操作"; + + actions[4].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY; + actions[4].description = "文本复制"; + + actions[5].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE; + actions[5].description = "文本粘贴"; + + actions[6].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT; + actions[6].description = "文本剪切"; + + actions[7].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT; + actions[7].description = "文本选择"; + + actions[8].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT; + actions[8].description = "文本内容设置"; + + actions[9].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION; + actions[9].description = "光标位置设置"; + + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions) + ); + } else if (widget_type == "scrollable") { + // if node is a scrollable component + int32_t actionTypeNum = 5; + ArkUI_AccessibleAction actions[actionTypeNum]; + + actions[0].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; + actions[0].description = "获取焦点"; + + actions[1].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].description = "清除焦点"; + + actions[2].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; + actions[2].description = "点击动作"; + + actions[3].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD; + actions[3].description = "向上滑动"; + + actions[4].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD; + actions[4].description = "向下滑动"; + + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions) + ); + } else { + // set common component action types + int32_t actionTypeNum = 3; + ArkUI_AccessibleAction actions[actionTypeNum]; + + actions[0].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; + actions[0].description = "获取焦点"; + + actions[1].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS; + actions[1].description = "清除焦点"; + + actions[2].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; + actions[2].description = "点击动作"; + + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions) + ); + } + } } /** @@ -860,216 +1121,319 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId) { - flutter::SemanticsNode flutterNode = - GetFlutterSemanticsNode(static_cast(elementId)); - - // set elementinfo id - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, - flutterNode.id) - ); - - // convert relative rect to absolute rect - ConvertChildRelativeRectToScreenRect(flutterNode); - auto rectPairs = GetAbsoluteScreenRect(flutterNode.id); - // set screen rect in xcomponent - int32_t left = rectPairs.first.first; - int32_t top = rectPairs.first.second; - int32_t right = rectPairs.second.first; - int32_t bottom = rectPairs.second.second; - ArkUI_AccessibleRect rect = {left, top, right, bottom}; - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect) - ); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> node.id= " - << flutterNode.id << " SceenRect = (" << left << ", " << top - << ", " << right << ", " << bottom << ")"; - - // 配置arkui的elementinfo可操作动作属性 - if (IsTextField(flutterNode)) { - // 若当前flutter节点为文本输入框组件 - std::string widget_type = "textfield"; - FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); - } else if (IsScrollableWidget(flutterNode) || IsNodeScrollable(flutterNode)) { - // 若当前flutter节点为可滑动组件类型 - std::string widget_type = "scrollable"; - FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); - } else { - // 若当前flutter节点为通用组件 - std::string widget_type = "common"; - FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); - } - - // set current elementinfo parent id - int32_t parentId = GetParentId(elementId); - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, parentId) - ); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById GetParentId = " << parentId; - - - // set accessibility text for announcing - std::string text = flutterNode.label; - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfoFromList, - text.c_str()) - ); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetAccessibilityText = " - << text; - //set contents (same as AccessibilityText) - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, text.c_str()) - ); - std::string hint = flutterNode.hint; - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetHintText(elementInfoFromList, - hint.c_str()) - ); - - // set chidren elementinfo ids - int32_t childCount = flutterNode.childrenInTraversalOrder.size(); - auto childrenIdsVec = flutterNode.childrenInTraversalOrder; - std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); - int64_t childNodeIds[childCount]; - for (int32_t i = 0; i < childCount; i++) { - childNodeIds[i] = static_cast(childrenIdsVec[i]); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> elementid=" << elementId - << " childCount=" << childCount - << " childNodeIds=" << childNodeIds[i]; - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, - childCount, childNodeIds) - ); - - /** - * 根据当前flutter节点的SemanticsFlags特性,配置对应的elmentinfo属性 - */ - // 判断当前节点是否可点击 - if (IsNodeClickable(flutterNode)) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetClickable -> true"; - } - // 判断当前节点是否可获焦点 - if (IsNodeFocusable(flutterNode)) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetFocusable -> true"; - } - // 判断当前节点是否为密码输入框 - if (IsNodePassword(flutterNode)) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetIsPassword(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetIsPassword -> true"; - } - // 判断当前节点是否具备checkable状态 (如:checkbox, radio button) - if (IsNodeCheckable(flutterNode)) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetCheckable -> true"; - } - // 判断当前节点(check box/radio button)是否checked/unchecked - if (IsNodeChecked(flutterNode)) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetChecked(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetChecked -> true"; - } - // 判断当前节点组件是否可显示 - if (IsNodeVisible(flutterNode)) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetVisible -> true"; - } - // 判断当前节点组件是否选中 - if (IsNodeSelected(flutterNode)) { - OH_ArkUI_AccessibilityElementInfoSetSelected(elementInfoFromList, true); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetSelected -> true"; - } - // 判断当前节点组件是否可滑动 - if (IsNodeScrollable(flutterNode)) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetScrollable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetScrollable -> true"; - } - // 判断当前节点组件是否可编辑(文本输入框) - if (IsTextField(flutterNode)) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetEditable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetEditable -> true"; - } - // 判断当前节点组件是否为滑动条 - if (IsSlider(flutterNode)) { - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetRangeInfo -> true"; - } - // 判断当前节点组件是否支持长按 - if (IsNodeHasLongPress(flutterNode)) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetLongClickable(elementInfoFromList, true) - ); - FML_DLOG(INFO) - << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetLongClickable -> true"; - } - // 判断当前节点组件是否enabled - if (IsNodeEnabled(flutterNode)) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetEnabled -> true"; - } - - // 获取当前节点的组件类型 - std::string componentTypeName = GetNodeComponentType(flutterNode); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById componentTypeName = " - << componentTypeName; - // flutter节点对应elementinfo所属的组件类型(如:root, button,text等) - if (elementId == 0) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root") - ); - } else { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, - componentTypeName.c_str()) - ); - } - FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetComponentType: " - << componentTypeName; - - /** - * 无障碍重要性,用于控制某个组件是否可被无障碍辅助服务所识别。支持的值为(默认值:“auto”): - * “auto”:根据组件不同会转换为“yes”或者“no” - * “yes”:当前组件可被无障碍辅助服务所识别 - * “no”:当前组件不可被无障碍辅助服务所识别 - * “no-hide-descendants”:当前组件及其所有子组件不可被无障碍辅助服务所识别 - */ - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes"); - ); - // 无障碍组,设置为true时表示该组件及其所有子组件为一整个可以选中的组件,无障碍服务将不再关注其子组件内容。默认值:false - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, false); - ); + if (OH_GetSdkApiVersion() >= 13) { + flutter::SemanticsNode flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); + + // set elementinfo id + int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetElementId"); + if (OH_ArkUI_AccessibilityElementInfoSetElementId == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetElementId is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, flutterNode.id) + ); + + // convert relative rect to absolute rect + ConvertChildRelativeRectToScreenRect(flutterNode); + auto rectPairs = GetAbsoluteScreenRect(flutterNode.id); + // set screen rect in xcomponent + int32_t left = rectPairs.first.first; + int32_t top = rectPairs.first.second; + int32_t right = rectPairs.second.first; + int32_t bottom = rectPairs.second.second; + ArkUI_AccessibleRect rect = {left, top, right, bottom}; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetScreenRect)(ArkUI_AccessibilityElementInfo*, ArkUI_AccessibleRect*) = + OhosAccessibilityDDL::DLLoadSetElemSreenRectFunc("OH_ArkUI_AccessibilityElementInfoSetScreenRect"); + if (OH_ArkUI_AccessibilityElementInfoSetScreenRect == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetScreenRect is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect) + ); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> node.id= " + << flutterNode.id << " SceenRect = (" << left << ", " << top + << ", " << right << ", " << bottom << ")"; + + // 配置arkui的elementinfo可操作动作属性 + if (IsTextField(flutterNode)) { + // 若当前flutter节点为文本输入框组件 + std::string widget_type = "textfield"; + FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); + } else if (IsScrollableWidget(flutterNode) || IsNodeScrollable(flutterNode)) { + // 若当前flutter节点为可滑动组件类型 + std::string widget_type = "scrollable"; + FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); + } else { + // 若当前flutter节点为通用组件 + std::string widget_type = "common"; + FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); + } + + // set current elementinfo parent id + int32_t parentId = GetParentId(elementId); + int32_t (*OH_ArkUI_AccessibilityElementInfoSetParentId)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetParentId"); + if (OH_ArkUI_AccessibilityElementInfoSetParentId == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetParentId is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, parentId) + ); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById GetParentId = " << parentId; + + // set accessibility text for announcing + std::string text = flutterNode.label; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityText)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText"); + if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityText == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfoFromList, text.c_str()) + ); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetAccessibilityText = " + << text; + + //set contents (same as AccessibilityText) + int32_t (*OH_ArkUI_AccessibilityElementInfoSetContents)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetContents"); + if (OH_ArkUI_AccessibilityElementInfoSetContents == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetContents is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, text.c_str()) + ); + + std::string hint = flutterNode.hint; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetHintText)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetHintText"); + if (OH_ArkUI_AccessibilityElementInfoSetHintText == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetHintText is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetHintText(elementInfoFromList, hint.c_str()) + ); + + // set chidren elementinfo ids + int32_t childCount = flutterNode.childrenInTraversalOrder.size(); + auto childrenIdsVec = flutterNode.childrenInTraversalOrder; + std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); + int64_t childNodeIds[childCount]; + for (int32_t i = 0; i < childCount; i++) { + childNodeIds[i] = static_cast(childrenIdsVec[i]); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> elementid=" << elementId + << " childCount=" << childCount + << " childNodeIds=" << childNodeIds[i]; + } + int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = + OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); + if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds) + ); + + /** + * 根据当前flutter节点的SemanticsFlags特性,配置对应的elmentinfo属性 + */ + // 判断当前节点是否可点击 + if (IsNodeClickable(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); + if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetClickable -> true"; + } + // 判断当前节点是否可获焦点 + if (IsNodeFocusable(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetFocusable"); + if (OH_ArkUI_AccessibilityElementInfoSetFocusable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetFocusable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetFocusable -> true"; + } + // 判断当前节点是否为密码输入框 + if (IsNodePassword(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetIsPassword)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetIsPassword"); + if (OH_ArkUI_AccessibilityElementInfoSetIsPassword == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetIsPassword is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetIsPassword(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetIsPassword -> true"; + } + // 判断当前节点是否具备checkable状态 (如:checkbox, radio button) + if (IsNodeCheckable(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetCheckable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetCheckable"); + if (OH_ArkUI_AccessibilityElementInfoSetCheckable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetCheckable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetCheckable -> true"; + } + // 判断当前节点(check box/radio button)是否checked/unchecked + if (IsNodeChecked(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetChecked)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetChecked"); + if (OH_ArkUI_AccessibilityElementInfoSetChecked == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetChecked is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetChecked(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetChecked -> true"; + } + // 判断当前节点组件是否可显示 + if (IsNodeVisible(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetVisible)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetVisible"); + if (OH_ArkUI_AccessibilityElementInfoSetVisible == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetVisible is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetVisible -> true"; + } + // 判断当前节点组件是否选中 + if (IsNodeSelected(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetSelected)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetSelected"); + if (OH_ArkUI_AccessibilityElementInfoSetSelected == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetSelected is null, %{public}s", dlerror()); + } + OH_ArkUI_AccessibilityElementInfoSetSelected(elementInfoFromList, true); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetSelected -> true"; + } + // 判断当前节点组件是否可滑动 + if (IsNodeScrollable(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetScrollable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetScrollable"); + if (OH_ArkUI_AccessibilityElementInfoSetScrollable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetScrollable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetScrollable(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetScrollable -> true"; + } + // 判断当前节点组件是否可编辑(文本输入框) + if (IsTextField(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEditable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEditable"); + if (OH_ArkUI_AccessibilityElementInfoSetEditable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetEditable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetEditable(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetEditable -> true"; + } + // 判断当前节点组件是否为滑动条 + if (IsSlider(flutterNode)) { + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetRangeInfo -> true"; + } + // 判断当前节点组件是否支持长按 + if (IsNodeHasLongPress(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetLongClickable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetLongClickable"); + if (OH_ArkUI_AccessibilityElementInfoSetLongClickable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetLongClickable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetLongClickable(elementInfoFromList, true) + ); + FML_DLOG(INFO) + << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetLongClickable -> true"; + } + // 判断当前节点组件是否enabled + if (IsNodeEnabled(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); + if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetEnabled -> true"; + } + + // 获取当前节点的组件类型 + std::string componentTypeName = GetNodeComponentType(flutterNode); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById componentTypeName = " + << componentTypeName; + // flutter节点对应elementinfo所属的组件类型(如:root, button,text等) + int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetComponentType"); + if (OH_ArkUI_AccessibilityElementInfoSetComponentType == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetComponentType is null, %{public}s", dlerror()); + } + if (elementId == 0) { + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root") + ); + } else { + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, + componentTypeName.c_str()) + ); + } + FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetComponentType: " + << componentTypeName; + + /** + * 无障碍重要性,用于控制某个组件是否可被无障碍辅助服务所识别。支持的值为(默认值:“auto”): + * “auto”:根据组件不同会转换为“yes”或者“no” + * “yes”:当前组件可被无障碍辅助服务所识别 + * “no”:当前组件不可被无障碍辅助服务所识别 + * “no-hide-descendants”:当前组件及其所有子组件不可被无障碍辅助服务所识别 + */ + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel"); + if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes"); + ); + // 无障碍组,设置为true时表示该组件及其所有子组件为一整个可以选中的组件,无障碍服务将不再关注其子组件内容。默认值:false + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup"); + if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, false); + ); + } } /** @@ -1111,23 +1475,30 @@ void OhosAccessibilityBridge::BuildArkUISemanticsTree( ArkUI_AccessibilityElementInfo* elementInfoFromList, ArkUI_AccessibilityElementInfoList* elementList) { - //配置root节点信息 - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - //获取flutter无障碍语义树的节点总数 - auto levelOrderTreeVec = GetLevelOrderTraversalTree(0); - int64_t elementInfoCount = levelOrderTreeVec.size(); - //创建并配置节点id >= 1的全部节点 - for (int64_t i = 1; i < elementInfoCount; i++) { - int64_t levelOrderId = levelOrderTreeVec[i]; - auto newNode = GetFlutterSemanticsNode(levelOrderId); - //当节点为隐藏状态时,自动规避 - if (IsNodeVisible(newNode)) { - ArkUI_AccessibilityElementInfo* newElementInfo = - OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); - //配置当前子节点信息 - FlutterNodeToElementInfoById(newElementInfo, levelOrderId); + if (OH_GetSdkApiVersion() >= 13) { + //配置root节点信息 + FlutterNodeToElementInfoById(elementInfoFromList, elementId); + //获取flutter无障碍语义树的节点总数 + auto levelOrderTreeVec = GetLevelOrderTraversalTree(0); + int64_t elementInfoCount = levelOrderTreeVec.size(); + //创建并配置节点id >= 1的全部节点 + for (int64_t i = 1; i < elementInfoCount; i++) { + int64_t levelOrderId = levelOrderTreeVec[i]; + auto newNode = GetFlutterSemanticsNode(levelOrderId); + //当节点为隐藏状态时,自动规避 + if (IsNodeVisible(newNode)) { + ArkUI_AccessibilityElementInfo* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = + OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); + if (OH_ArkUI_AddAndGetAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_AddAndGetAccessibilityElementInfo is null, %{public}s", dlerror()); + } + ArkUI_AccessibilityElementInfo* newElementInfo = + OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + //配置当前子节点信息 + FlutterNodeToElementInfoById(newElementInfo, levelOrderId); + } + } } - } } /** @@ -1140,79 +1511,76 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { - FML_DLOG(INFO) - << "#### FindAccessibilityNodeInfosById input-params ####: elementId = " - << elementId << " mode=" << mode << " requestId=" << requestId - << " elementList= " << elementList; - - if (g_flutterSemanticsTree.size() == 0) { - FML_DLOG(INFO) - << "FindAccessibilityNodeInfosById g_flutterSemanticsTree is null"; - return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; - } - if (elementList == nullptr) { - FML_DLOG(INFO) << "FindAccessibilityNodeInfosById elementList is null"; - return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; - } - - // 开启无障碍导航功能 - if(elementId == -1 || elementId == 0) { - accessibilityFeatures_->SetAccessibleNavigation(true, native_shell_holder_id_); - } - - // 从elementinfolist中获取elementinfo - ArkUI_AccessibilityElementInfo* elementInfoFromList = - OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); - if (elementInfoFromList == nullptr) { FML_DLOG(INFO) - << "FindAccessibilityNodeInfosById elementInfoFromList is null"; - return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; - } + << "#### FindAccessibilityNodeInfosById input-params ####: elementId = " + << elementId << " mode=" << mode << " requestId=" << requestId + << " elementList= " << elementList; - // 过滤非当前屏幕显示的语义节点创建、配置,防止溢出屏幕坐标绘制bug以及优化性能开销 - auto flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); - bool VISIBLE_STATE = elementId == -1; - if (!VISIBLE_STATE && !IsNodeVisible(flutterNode)) { - FML_DLOG(INFO) << "filter hidden nodes, elementId:" << elementId; - return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; - } + if (g_flutterSemanticsTree.size() == 0) { + FML_DLOG(INFO) + << "FindAccessibilityNodeInfosById g_flutterSemanticsTree is null"; + return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; + } + if (elementList == nullptr) { + FML_DLOG(INFO) << "FindAccessibilityNodeInfosById elementList is null"; + return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; + } - if (mode == ArkUI_AccessibilitySearchMode:: - ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { - /** Search for current nodes. (mode = 0) */ - BuildArkUISemanticsTree(elementId, elementInfoFromList, elementList); - } else if (mode == - ArkUI_AccessibilitySearchMode:: - ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS) { - /** Search for parent nodes. (mode = 1) */ - if (IsNodeVisible(flutterNode)) { - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - } - } else if (mode == - ArkUI_AccessibilitySearchMode:: - ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_SIBLINGS) { - /** Search for sibling nodes. (mode = 2) */ - if (IsNodeVisible(flutterNode)) { - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - } - } else if (mode == - ArkUI_AccessibilitySearchMode:: - ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CHILDREN) { - /** Search for child nodes at the next level. (mode = 4) */ - if (IsNodeVisible(flutterNode)) { - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - } - } else if ( - mode == - ArkUI_AccessibilitySearchMode:: - ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_RECURSIVE_CHILDREN) { - /** Search for all child nodes. (mode = 8) */ - BuildArkUISemanticsTree(elementId, elementInfoFromList, elementList); - } else { - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - } - FML_DLOG(INFO) << "--- FindAccessibilityNodeInfosById is end ---"; - return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; + if (OH_GetSdkApiVersion() >= 13) { + // 开启无障碍导航功能 + if(elementId == -1 || elementId == 0) { + accessibilityFeatures_->SetAccessibleNavigation(true, native_shell_holder_id_); + } + + // 从elementinfolist中获取elementinfo + ArkUI_AccessibilityElementInfo* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = + OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); + if (OH_ArkUI_AddAndGetAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_AddAndGetAccessibilityElementInfo is null, %{public}s", dlerror()); + } + ArkUI_AccessibilityElementInfo* elementInfoFromList = + OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + if (elementInfoFromList == nullptr) { + FML_DLOG(INFO) + << "FindAccessibilityNodeInfosById elementInfoFromList is null"; + return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; + } + + // 过滤非当前屏幕显示的语义节点创建、配置,防止溢出屏幕坐标绘制bug以及优化性能开销 + auto flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); + bool VISIBLE_STATE = elementId == -1; + if (!VISIBLE_STATE && !IsNodeVisible(flutterNode)) { + FML_DLOG(INFO) << "filter hidden nodes, elementId:" << elementId; + return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; + } + + if (mode == ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { + /** Search for current nodes. (mode = 0) */ + BuildArkUISemanticsTree(elementId, elementInfoFromList, elementList); + } else if (mode ==ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS) { + /** Search for parent nodes. (mode = 1) */ + if (IsNodeVisible(flutterNode)) { + FlutterNodeToElementInfoById(elementInfoFromList, elementId); + } + } else if (mode ==ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_SIBLINGS) { + /** Search for sibling nodes. (mode = 2) */ + if (IsNodeVisible(flutterNode)) { + FlutterNodeToElementInfoById(elementInfoFromList, elementId); + } + } else if (mode ==ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CHILDREN) { + /** Search for child nodes at the next level. (mode = 4) */ + if (IsNodeVisible(flutterNode)) { + FlutterNodeToElementInfoById(elementInfoFromList, elementId); + } + } else if (mode ==ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_RECURSIVE_CHILDREN) { + /** Search for all child nodes. (mode = 8) */ + BuildArkUISemanticsTree(elementId, elementInfoFromList, elementList); + } else { + FlutterNodeToElementInfoById(elementInfoFromList, elementId); + } + } + FML_DLOG(INFO) << "--- FindAccessibilityNodeInfosById is end ---"; + return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; } /** @@ -1223,10 +1591,10 @@ void OhosAccessibilityBridge::DispatchSemanticsAction( flutter::SemanticsAction action, fml::MallocMapping args) { - nativeAccessibilityChannel_->DispatchSemanticsAction(native_shell_holder_id_, - id, - action, - fml::MallocMapping()); + nativeAccessibilityChannel_->DispatchSemanticsAction(native_shell_holder_id_, + id, + action, + fml::MallocMapping()); } /** @@ -1238,240 +1606,221 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( ArkUI_AccessibilityActionArguments* actionArguments, int32_t requestId) { - FML_DLOG(INFO) << "ExecuteAccessibilityAction input-params-> elementId=" - << elementId << " action=" << action - << " requestId=" << requestId - << " *actionArguments=" << actionArguments; - - if (actionArguments == nullptr) { - FML_DLOG(ERROR) << "OhosAccessibilityBridge::ExecuteAccessibilityAction " - "actionArguments = null"; - return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; - } + FML_DLOG(INFO) << "ExecuteAccessibilityAction input-params-> elementId=" + << elementId << " action=" << action + << " requestId=" << requestId + << " *actionArguments=" << actionArguments; + + if (actionArguments == nullptr) { + FML_DLOG(ERROR) << "OhosAccessibilityBridge::ExecuteAccessibilityAction " + "actionArguments = null"; + return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; + } - // 获取当前elementid对应的flutter语义节点 - auto flutterNode = - GetFlutterSemanticsNode(static_cast(elementId)); - - // 根据当前elementid和无障碍动作类型,发送无障碍事件 - switch (action) { - /** Response to a click. 16 */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: { - /** Click event, sent after the UI component responds. 1 */ - auto clickEventType = ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_CLICKED; - Flutter_SendAccessibilityAsyncEvent(elementId, clickEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: click(" << action - << ")" << " event: click(" << clickEventType << ")"; - // 解析arkui的屏幕点击 -> flutter对应节点的屏幕点击 - auto flutterTapAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), flutterTapAction, - {}); - break; - } - /** Response to a long click. 32 */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: { - /** Long click event, sent after the UI component responds. 2 */ - auto longClickEventType = ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_LONG_CLICKED; - Flutter_SendAccessibilityAsyncEvent(elementId, longClickEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: longclick(" - << action << ")" << " event: longclick(" - << longClickEventType << ")"; - // 解析arkui的屏幕动作 -> flutter对应节点的屏幕动作 - auto flutterLongPressAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), - flutterLongPressAction, {}); - break; - } - /** Accessibility focus acquisition. 64 */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: { - // 解析arkui的获焦 -> flutter对应节点的获焦 - auto flutterGainFocusAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), - flutterGainFocusAction, {}); - // Accessibility focus event, sent after the UI component responds. 32768 - auto focusEventType = ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; - Flutter_SendAccessibilityAsyncEvent(elementId, focusEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: focus(" << action - << ")" << " event: focus(" << focusEventType << ")"; - if (flutterNode.HasAction(ACTIONS_::kIncrease) || - flutterNode.HasAction(ACTIONS_::kDecrease)) { - Flutter_SendAccessibilityAsyncEvent( - elementId, ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + // 获取当前elementid对应的flutter语义节点 + auto flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); + + // 根据当前elementid和无障碍动作类型,发送无障碍事件 + switch (action) { + /** Response to a click. 16 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: { + /** Click event, sent after the UI component responds. 1 */ + auto clickEventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_CLICKED; + Flutter_SendAccessibilityAsyncEvent(elementId, clickEventType); + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: click(" << action + << ")" << " event: click(" << clickEventType << ")"; + // 解析arkui的屏幕点击 -> flutter对应节点的屏幕点击 + auto flutterTapAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), flutterTapAction, + {}); + break; } - break; - } - /** Accessibility focus clearance. 128 */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: { - // 解析arkui的失焦 -> flutter对应节点的失焦 - auto flutterLoseFocusAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), - flutterLoseFocusAction, {}); - /** Accessibility focus cleared event, sent after the UI component - * responds. 65536 */ - auto clearFocusEventType = ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED; - Flutter_SendAccessibilityAsyncEvent(elementId, clearFocusEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: clearfocus(" - << action << ")" << " event: clearfocus(" - << clearFocusEventType << ")"; - break; - } - /** Forward scroll action. 256 */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: { - // flutter scroll forward with different situations - if (flutterNode.HasAction(ACTIONS_::kScrollUp)) { - auto flutterScrollUpAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), - flutterScrollUpAction, {}); - } else if (flutterNode.HasAction(ACTIONS_::kScrollLeft)) { - DispatchSemanticsAction(static_cast(elementId), - ACTIONS_::kScrollLeft, {}); - } else if (flutterNode.HasAction(ACTIONS_::kIncrease)) { - flutterNode.value = flutterNode.increasedValue; - flutterNode.valueAttributes = flutterNode.increasedValueAttributes; - - Flutter_SendAccessibilityAsyncEvent( - elementId, ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); - DispatchSemanticsAction(static_cast(elementId), - ACTIONS_::kIncrease, {}); - } else { + /** Response to a long click. 32 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: { + /** Long click event, sent after the UI component responds. 2 */ + auto longClickEventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_LONG_CLICKED; + Flutter_SendAccessibilityAsyncEvent(elementId, longClickEventType); + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: longclick(" + << action << ")" << " event: longclick(" + << longClickEventType << ")"; + // 解析arkui的屏幕动作 -> flutter对应节点的屏幕动作 + auto flutterLongPressAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), + flutterLongPressAction, {}); + break; } - std::string currComponetType = GetNodeComponentType(flutterNode); - if (currComponetType == "ListView") { - /** Scrolled event, sent when a scrollable component experiences a - * scroll event. 4096 */ - ArkUI_AccessibilityEventType scrollEventType1 = - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; - Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); - FML_DLOG(INFO) - << "ExecuteAccessibilityAction -> action: scroll forward(" << action - << ")" << " event: scroll forward(" << scrollEventType1 << ")"; + /** Accessibility focus acquisition. 64 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: { + // 解析arkui的获焦 -> flutter对应节点的获焦 + auto flutterGainFocusAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), + flutterGainFocusAction, {}); + // Accessibility focus event, sent after the UI component responds. 32768 + auto focusEventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; + Flutter_SendAccessibilityAsyncEvent(elementId, focusEventType); + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: focus(" << action + << ")" << " event: focus(" << focusEventType << ")"; + if (flutterNode.HasAction(ACTIONS_::kIncrease) || + flutterNode.HasAction(ACTIONS_::kDecrease)) { + Flutter_SendAccessibilityAsyncEvent( + elementId, ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + } + break; } - break; - } - /** Backward scroll action. 512 */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: { - // flutter scroll down with different situations - if (flutterNode.HasAction(ACTIONS_::kScrollDown)) { - auto flutterScrollDownAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), - flutterScrollDownAction, {}); - } else if (flutterNode.HasAction(ACTIONS_::kScrollRight)) { - DispatchSemanticsAction(static_cast(elementId), - ACTIONS_::kScrollRight, {}); - } else if (flutterNode.HasAction(ACTIONS_::kDecrease)) { - flutterNode.value = flutterNode.decreasedValue; - flutterNode.valueAttributes = flutterNode.decreasedValueAttributes; - - Flutter_SendAccessibilityAsyncEvent( - elementId, ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); - DispatchSemanticsAction(static_cast(elementId), - ACTIONS_::kDecrease, {}); - } else { + /** Accessibility focus clearance. 128 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: { + // 解析arkui的失焦 -> flutter对应节点的失焦 + auto flutterLoseFocusAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), + flutterLoseFocusAction, {}); + /** Accessibility focus cleared event, sent after the UI component + * responds. 65536 */ + auto clearFocusEventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED; + Flutter_SendAccessibilityAsyncEvent(elementId, clearFocusEventType); + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: clearfocus(" + << action << ")" << " event: clearfocus(" + << clearFocusEventType << ")"; + break; } - std::string currComponetType = GetNodeComponentType(flutterNode); - if (currComponetType == "ListView") { - /** Scrolled event, sent when a scrollable component experiences a - * scroll event. 4096 */ - ArkUI_AccessibilityEventType scrollBackwardEventType = - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; - Flutter_SendAccessibilityAsyncEvent(elementId, scrollBackwardEventType); - FML_DLOG(INFO) - << "ExecuteAccessibilityAction -> action: scroll backward(" - << action << ")" << " event: scroll backward(" - << scrollBackwardEventType << ")"; + /** Forward scroll action. 256 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: { + // flutter scroll forward with different situations + if (flutterNode.HasAction(ACTIONS_::kScrollUp)) { + auto flutterScrollUpAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), + flutterScrollUpAction, {}); + } else if (flutterNode.HasAction(ACTIONS_::kScrollLeft)) { + DispatchSemanticsAction(static_cast(elementId), + ACTIONS_::kScrollLeft, {}); + } else if (flutterNode.HasAction(ACTIONS_::kIncrease)) { + flutterNode.value = flutterNode.increasedValue; + flutterNode.valueAttributes = flutterNode.increasedValueAttributes; + + Flutter_SendAccessibilityAsyncEvent( + elementId, ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + DispatchSemanticsAction(static_cast(elementId), + ACTIONS_::kIncrease, {}); + } else { + } + std::string currComponetType = GetNodeComponentType(flutterNode); + if (currComponetType == "ListView") { + /** Scrolled event, sent when a scrollable component experiences a + * scroll event. 4096 */ + ArkUI_AccessibilityEventType scrollEventType1 = + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); + FML_DLOG(INFO) + << "ExecuteAccessibilityAction -> action: scroll forward(" << action + << ")" << " event: scroll forward(" << scrollEventType1 << ")"; + } + break; + } + /** Backward scroll action. 512 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: { + // flutter scroll down with different situations + if (flutterNode.HasAction(ACTIONS_::kScrollDown)) { + auto flutterScrollDownAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), + flutterScrollDownAction, {}); + } else if (flutterNode.HasAction(ACTIONS_::kScrollRight)) { + DispatchSemanticsAction(static_cast(elementId), + ACTIONS_::kScrollRight, {}); + } else if (flutterNode.HasAction(ACTIONS_::kDecrease)) { + flutterNode.value = flutterNode.decreasedValue; + flutterNode.valueAttributes = flutterNode.decreasedValueAttributes; + + Flutter_SendAccessibilityAsyncEvent( + elementId, ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + DispatchSemanticsAction(static_cast(elementId), + ACTIONS_::kDecrease, {}); + } else { + } + std::string currComponetType = GetNodeComponentType(flutterNode); + if (currComponetType == "ListView") { + /** Scrolled event, sent when a scrollable component experiences a + * scroll event. 4096 */ + ArkUI_AccessibilityEventType scrollBackwardEventType = + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + Flutter_SendAccessibilityAsyncEvent(elementId, scrollBackwardEventType); + FML_DLOG(INFO) + << "ExecuteAccessibilityAction -> action: scroll backward(" + << action << ")" << " event: scroll backward(" + << scrollBackwardEventType << ")"; + } + break; + } + /** Copy action for text content. 1024 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: copy(" << action + << ")"; + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCopy, {}); + break; + } + /** Paste action for text content. 2048 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE: { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: paste(" << action + << ")"; + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kPaste, {}); + break; + } + /** Cut action for text content. 4096 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: cut(" << action << ")"; + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCut, {}); + break; + } + /** Text selection action, requiring the setting of selectTextBegin, + * TextEnd, and TextInForward parameters to select a text + * segment in the text box. 8192 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: select text(" + << action << ")"; + // 输入框文本选择操作 + PerformSelectText(flutterNode, action, actionArguments); + break; + } + /** Text content setting action. 16384 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: set text(" + << action << ")"; + // 输入框设置文本 + PerformSetText(flutterNode, action, actionArguments); + break; + } + /** Cursor position setting action. 1048576 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION: { + FML_DLOG(INFO) + << "ExecuteAccessibilityAction -> action: set cursor position(" + << action << ")"; + break; + } + /** Invalid action. 0 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID: { + /** Invalid event. 0 */ + ArkUI_AccessibilityEventType invalidEventType = + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_INVALID; + Flutter_SendAccessibilityAsyncEvent(elementId, invalidEventType); + FML_DLOG(ERROR) << "ExecuteAccessibilityAction -> action: invalid(" + << action << ")" << " event: innvalid(" + << invalidEventType << ")"; + break; + } + default: { + /** custom semantics action */ } - break; - } - /** Copy action for text content. 1024 */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: copy(" << action - << ")"; - DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCopy, - {}); - break; - } - /** Paste action for text content. 2048 */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: paste(" << action - << ")"; - DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kPaste, - {}); - break; - } - /** Cut action for text content. 4096 */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: cut(" << action - << ")"; - DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCut, - {}); - break; - /** Text selection action, requiring the setting of selectTextBegin, - * TextEnd, and TextInForward parameters to select a text - * segment in the text box. 8192 */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: select text(" - << action << ")"; - // 输入框文本选择操作 - PerformSelectText(flutterNode, action, actionArguments); - break; - } - /** Text content setting action. 16384 */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: set text(" - << action << ")"; - // 输入框设置文本 - PerformSetText(flutterNode, action, actionArguments); - break; - } - /** Cursor position setting action. 1048576 */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION: { - FML_DLOG(INFO) - << "ExecuteAccessibilityAction -> action: set cursor position(" - << action << ")"; - // 当前os接口不支持该功能,不影响正常屏幕朗读 - break; - } - /** Invalid action. 0 */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID: { - /** Invalid event. 0 */ - ArkUI_AccessibilityEventType invalidEventType = - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_INVALID; - Flutter_SendAccessibilityAsyncEvent(elementId, invalidEventType); - FML_DLOG(ERROR) << "ExecuteAccessibilityAction -> action: invalid(" - << action << ")" << " event: innvalid(" - << invalidEventType << ")"; - break; - } - default: { - /** custom semantics action */ } - } - - FML_DLOG(INFO) << "--- ExecuteAccessibilityAction is end ---"; - return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; + FML_DLOG(INFO) << "--- ExecuteAccessibilityAction is end ---"; + return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; } /** @@ -1484,8 +1833,8 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosByText( int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { - FML_DLOG(INFO) << "=== FindAccessibilityNodeInfosByText is end ==="; - return 0; + FML_DLOG(INFO) << "=== FindAccessibilityNodeInfosByText() ==="; + return 0; } int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( int64_t elementId, @@ -1493,31 +1842,30 @@ int32_t OhosAccessibilityBridge::FindFocusedAccessibilityNode( int32_t requestId, ArkUI_AccessibilityElementInfo* elementinfo) { - FML_DLOG(INFO) << "=== FindFocusedAccessibilityNode is end ==="; - - return 0; + FML_DLOG(INFO) << "=== FindFocusedAccessibilityNode() ==="; + return 0; } int32_t OhosAccessibilityBridge::FindNextFocusAccessibilityNode( int64_t elementId, ArkUI_AccessibilityFocusMoveDirection direction, int32_t requestId, ArkUI_AccessibilityElementInfo* elementList) { - FML_DLOG(INFO) << "=== FindNextFocusAccessibilityNode is end ==="; - return 0; + FML_DLOG(INFO) << "=== FindNextFocusAccessibilityNode() ==="; + return 0; } int32_t OhosAccessibilityBridge::ClearFocusedFocusAccessibilityNode() { - FML_DLOG(INFO) << "=== ClearFocusedFocusAccessibilityNode is end ==="; - return 0; + FML_DLOG(INFO) << "=== ClearFocusedFocusAccessibilityNode() ==="; + return 0; } int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( int64_t elementId, int32_t requestId, int32_t* index) { - FML_DLOG(INFO) << "=== GetAccessibilityNodeCursorPosition is end ==="; - return 0; + FML_DLOG(INFO) << "=== GetAccessibilityNodeCursorPosition() ==="; + return 0; } /** @@ -1526,54 +1874,54 @@ int32_t OhosAccessibilityBridge::GetAccessibilityNodeCursorPosition( flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( ArkUI_Accessibility_ActionType arkui_action) { - switch (arkui_action) { - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: - return ACTIONS_::kTap; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: - return ACTIONS_::kLongPress; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: - return ACTIONS_::kScrollUp; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: - return ACTIONS_::kScrollDown; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: - return ACTIONS_::kCopy; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: - return ACTIONS_::kCut; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: - return ACTIONS_::kDidGainAccessibilityFocus; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: - return ACTIONS_::kDidLoseAccessibilityFocus; - - // Text selection action, requiring the setting of selectTextBegin, - // TextEnd, and TextInForward parameters to select a text - // segment in the text box. */ - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: - return ACTIONS_::kSetSelection; - - case ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: - return ACTIONS_::kSetText; - - default: - // might not match to the valid action in arkui - return ACTIONS_::kCustomAction; - } + switch (arkui_action) { + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: + return ACTIONS_::kTap; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: + return ACTIONS_::kLongPress; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: + return ACTIONS_::kScrollUp; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: + return ACTIONS_::kScrollDown; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: + return ACTIONS_::kCopy; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: + return ACTIONS_::kCut; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: + return ACTIONS_::kDidGainAccessibilityFocus; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: + return ACTIONS_::kDidLoseAccessibilityFocus; + + // Text selection action, requiring the setting of selectTextBegin, + // TextEnd, and TextInForward parameters to select a text + // segment in the text box. */ + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: + return ACTIONS_::kSetSelection; + + case ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: + return ACTIONS_::kSetText; + + default: + // might not match to the valid action in arkui + return ACTIONS_::kCustomAction; + } } /** @@ -1583,59 +1931,96 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( int64_t elementId, ArkUI_AccessibilityEventType eventType) { - if (provider_ == nullptr) { - FML_DLOG(ERROR) << "Flutter_SendAccessibilityAsyncEvent " - "AccessibilityProvider = nullptr"; - return; - } - // 1.创建eventInfo对象 - ArkUI_AccessibilityEventInfo* eventInfo = - OH_ArkUI_CreateAccessibilityEventInfo(); - if (eventInfo == nullptr) { - FML_DLOG(ERROR) << "Flutter_SendAccessibilityAsyncEvent " - "OH_ArkUI_CreateAccessibilityEventInfo eventInfo = null"; - return; - } - - // 2.创建的elementinfo并根据对应id的flutternode进行属性初始化 - ArkUI_AccessibilityElementInfo* _elementInfo = - OH_ArkUI_CreateAccessibilityElementInfo(); - FlutterNodeToElementInfoById(_elementInfo, elementId); - // 若为获焦事件,则设置当前elementinfo获焦 - if (eventType == - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused(_elementInfo, - true) - ); - } - - // 3.设置发送事件,如配置获焦、失焦、点击、滑动事件 - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityEventSetEventType(eventInfo, eventType)); - - // 4.将eventinfo事件和当前elementinfo进行绑定 - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityEventSetElementInfo(eventInfo, _elementInfo)); + if (provider_ == nullptr) { + FML_DLOG(ERROR) << "Flutter_SendAccessibilityAsyncEvent " + "AccessibilityProvider = nullptr"; + return; + } + if (OH_GetSdkApiVersion() >= 13) { + // 1.创建eventInfo对象 + ArkUI_AccessibilityEventInfo* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = + OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); + if (OH_ArkUI_CreateAccessibilityEventInfo == nullptr) { + LOGE("OH_ArkUI_CreateAccessibilityEventInfo is null, %{public}s", dlerror()); + } + ArkUI_AccessibilityEventInfo* eventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); + if (eventInfo == nullptr) { + FML_DLOG(ERROR) << "Flutter_SendAccessibilityAsyncEvent " + "OH_ArkUI_CreateAccessibilityEventInfo eventInfo = null"; + return; + } + + // 2.创建的elementinfo并根据对应id的flutternode进行属性初始化 + ArkUI_AccessibilityElementInfo* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = + OhosAccessibilityDDL::DLLoadCreateElemInfoFunc("OH_ArkUI_CreateAccessibilityElementInfo"); + if (OH_ArkUI_CreateAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_CreateAccessibilityElementInfo is null, %{public}s", dlerror()); + } + ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); + FlutterNodeToElementInfoById(_elementInfo, elementId); + // 若为获焦事件,则设置当前elementinfo获焦 + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused"); + if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused is null, %{public}s", dlerror()); + } + if (eventType == ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED) { + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused(_elementInfo, true) + ); + } + + // 3.设置发送事件,如配置获焦、失焦、点击、滑动事件 + int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = + OhosAccessibilityDDL::DLLoadSetEventFunc("OH_ArkUI_AccessibilityEventSetEventType"); + if (OH_ArkUI_AccessibilityEventSetEventType == nullptr) { + LOGE("OH_ArkUI_AccessibilityEventSetEventType is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityEventSetEventType(eventInfo, eventType)); + + // 4.将eventinfo事件和当前elementinfo进行绑定 + int32_t (*OH_ArkUI_AccessibilityEventSetElementInfo)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityElementInfo*) = + OhosAccessibilityDDL::DLLoadSetEventElemFunc("OH_ArkUI_AccessibilityEventSetElementInfo"); + if (OH_ArkUI_AccessibilityEventSetElementInfo == nullptr) { + LOGE("OH_ArkUI_AccessibilityEventSetElementInfo is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityEventSetElementInfo(eventInfo, _elementInfo)); + + // 5.调用接口发送到ohos侧 + auto callback = [](int32_t errorCode) { + FML_DLOG(INFO) + << "Flutter_SendAccessibilityAsyncEvent callback-> errorCode =" + << errorCode; + }; + + // 6.发送event到OH侧 + void (*OH_ArkUI_SendAccessibilityAsyncEvent)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*callback)(int32_t)) = + OhosAccessibilityDDL::DLLoadSendAsyncEventFunc("OH_ArkUI_SendAccessibilityAsyncEvent"); + if (OH_ArkUI_SendAccessibilityAsyncEvent == nullptr) { + LOGE("OH_ArkUI_SendAccessibilityAsyncEvent is null, %{public}s", dlerror()); + } + OH_ArkUI_SendAccessibilityAsyncEvent(provider_, eventInfo, callback); + + // 7.销毁新创建的elementinfo, eventinfo + void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = + OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); + if (OH_ArkUI_DestoryAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_DestoryAccessibilityElementInfo is null, %{public}s", dlerror()); + } + OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); + _elementInfo = nullptr; + + void (*OH_ArkUI_DestoryAccessibilityEventInfo)(ArkUI_AccessibilityEventInfo*) = + OhosAccessibilityDDL::DLLoadDestroyEventFunc("OH_ArkUI_DestoryAccessibilityEventInfo"); + if (OH_ArkUI_DestoryAccessibilityEventInfo == nullptr) { + LOGE("OH_ArkUI_DestoryAccessibilityEventInfo is null, %{public}s", dlerror()); + } + OH_ArkUI_DestoryAccessibilityEventInfo(eventInfo); + eventInfo = nullptr; + } - // 5.调用接口发送到ohos侧 - auto callback = [](int32_t errorCode) { - FML_DLOG(INFO) - << "Flutter_SendAccessibilityAsyncEvent callback-> errorCode =" - << errorCode; - }; - - // 6.发送event到OH侧 - OH_ArkUI_SendAccessibilityAsyncEvent(provider_, eventInfo, callback); - - // 7.销毁新创建的elementinfo, eventinfo - OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); - _elementInfo = nullptr; - OH_ArkUI_DestoryAccessibilityEventInfo(eventInfo); - eventInfo = nullptr; - - FML_DLOG(INFO) - << "OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent is end"; - return; + FML_DLOG(INFO) << "OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent is end"; + return; } /** @@ -1644,28 +2029,28 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( bool OhosAccessibilityBridge::IsNodeFocusable( const flutter::SemanticsNode& node) { - if (node.HasFlag(FLAGS_::kScopesRoute)) { - return false; - } - if (node.HasFlag(FLAGS_::kIsFocusable)) { - return true; - } - // Always consider platform views focusable. - if (node.IsPlatformViewNode()) { - return true; - } - // Always consider actionable nodes focusable. - if (node.actions != 0) { - return true; - } - if ((node.flags & FOCUSABLE_FLAGS) != 0) { - return true; - } - if ((node.actions & ~FOCUSABLE_FLAGS) != 0) { - return true; - } - // Consider text nodes focusable. - return !node.label.empty() || !node.value.empty() || !node.hint.empty(); + if (node.HasFlag(FLAGS_::kScopesRoute)) { + return false; + } + if (node.HasFlag(FLAGS_::kIsFocusable)) { + return true; + } + // Always consider platform views focusable. + if (node.IsPlatformViewNode()) { + return true; + } + // Always consider actionable nodes focusable. + if (node.actions != 0) { + return true; + } + if ((node.flags & FOCUSABLE_FLAGS) != 0) { + return true; + } + if ((node.actions & ~FOCUSABLE_FLAGS) != 0) { + return true; + } + // Consider text nodes focusable. + return !node.label.empty() || !node.value.empty() || !node.hint.empty(); } void OhosAccessibilityBridge::PerformSetText( @@ -1684,55 +2069,55 @@ void OhosAccessibilityBridge::PerformSelectText( std::string OhosAccessibilityBridge::GetNodeComponentType( const flutter::SemanticsNode& node) { - if (node.HasFlag(FLAGS_::kIsButton)) { - return "Button"; - } - if (node.HasFlag(FLAGS_::kIsTextField)) { - return "TextField"; - } - if (node.HasFlag(FLAGS_::kIsMultiline)) { - return "TextArea"; - } - if (node.HasFlag(FLAGS_::kIsLink)) { - return "Link"; - } - if (node.HasFlag(FLAGS_::kIsSlider) || node.HasAction(ACTIONS_::kIncrease) || - node.HasAction(ACTIONS_::kDecrease)) { - return "Slider"; - } - if (node.HasFlag(FLAGS_::kIsHeader)) { - return "Header"; - } - if (node.HasFlag(FLAGS_::kIsImage)) { - return "Image"; - } - if (node.HasFlag(FLAGS_::kHasCheckedState)) { - if (node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup)) { - // arkui没有RadioButton,这里透传为RadioButton - return "RadioButton"; - } else { - return "Checkbox"; + if (node.HasFlag(FLAGS_::kIsButton)) { + return "Button"; } - } - if (node.HasFlag(FLAGS_::kHasToggledState)) { - return "Switch"; - } - if (node.HasFlag(FLAGS_::kHasImplicitScrolling)) { - if (node.HasAction(ACTIONS_::kScrollLeft) || - node.HasAction(ACTIONS_::kScrollRight)) { - return "HorizontalScrollView"; - } else { - return "ScrollView"; + if (node.HasFlag(FLAGS_::kIsTextField)) { + return "TextField"; } - } - if (node.HasAction(ACTIONS_::kIncrease) || - node.HasAction(ACTIONS_::kDecrease)) { - return "SeekBar"; - } - if ((!node.label.empty() || !node.tooltip.empty() || !node.hint.empty())) { - return "Text"; - } - return "Widget" + std::to_string(node.id); + if (node.HasFlag(FLAGS_::kIsMultiline)) { + return "TextArea"; + } + if (node.HasFlag(FLAGS_::kIsLink)) { + return "Link"; + } + if (node.HasFlag(FLAGS_::kIsSlider) || node.HasAction(ACTIONS_::kIncrease) || + node.HasAction(ACTIONS_::kDecrease)) { + return "Slider"; + } + if (node.HasFlag(FLAGS_::kIsHeader)) { + return "Header"; + } + if (node.HasFlag(FLAGS_::kIsImage)) { + return "Image"; + } + if (node.HasFlag(FLAGS_::kHasCheckedState)) { + if (node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup)) { + // arkui没有RadioButton,这里透传为RadioButton + return "RadioButton"; + } else { + return "Checkbox"; + } + } + if (node.HasFlag(FLAGS_::kHasToggledState)) { + return "Switch"; + } + if (node.HasAction(ACTIONS_::kIncrease) || + node.HasAction(ACTIONS_::kDecrease)) { + return "SeekBar"; + } + if (node.HasFlag(FLAGS_::kHasImplicitScrolling)) { + if (node.HasAction(ACTIONS_::kScrollLeft) || + node.HasAction(ACTIONS_::kScrollRight)) { + return "HorizontalScrollView"; + } else { + return "ScrollView"; + } + } + if ((!node.label.empty() || !node.tooltip.empty() || !node.hint.empty())) { + return "Text"; + } + return "Widget"; } /** @@ -1740,14 +2125,14 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( */ bool OhosAccessibilityBridge::IsTextField(flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kIsTextField); + return flutterNode.HasFlag(FLAGS_::kIsTextField); } /** * 判断当前节点是否为滑动条slider类型 */ bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kIsSlider); + return flutterNode.HasFlag(FLAGS_::kIsSlider); } /** * 判断当前flutter节点组件是否可点击 @@ -1755,18 +2140,18 @@ bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) bool OhosAccessibilityBridge::IsNodeClickable( flutter::SemanticsNode flutterNode) { - return flutterNode.HasAction(ACTIONS_::kTap) || - flutterNode.HasFlag(FLAGS_::kHasCheckedState) || - flutterNode.HasFlag(FLAGS_::kIsButton) || - flutterNode.HasFlag(FLAGS_::kIsTextField) || - flutterNode.HasFlag(FLAGS_::kIsImage) || - flutterNode.HasFlag(FLAGS_::kIsLiveRegion) || - flutterNode.HasFlag(FLAGS_::kIsMultiline) || - flutterNode.HasFlag(FLAGS_::kIsLink) || - flutterNode.HasFlag(FLAGS_::kIsSlider) || - flutterNode.HasFlag(FLAGS_::kIsKeyboardKey) || - flutterNode.HasFlag(FLAGS_::kHasToggledState) || - flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); + return flutterNode.HasAction(ACTIONS_::kTap) || + flutterNode.HasFlag(FLAGS_::kHasCheckedState) || + flutterNode.HasFlag(FLAGS_::kIsButton) || + flutterNode.HasFlag(FLAGS_::kIsTextField) || + flutterNode.HasFlag(FLAGS_::kIsImage) || + flutterNode.HasFlag(FLAGS_::kIsLiveRegion) || + flutterNode.HasFlag(FLAGS_::kIsMultiline) || + flutterNode.HasFlag(FLAGS_::kIsLink) || + flutterNode.HasFlag(FLAGS_::kIsSlider) || + flutterNode.HasFlag(FLAGS_::kIsKeyboardKey) || + flutterNode.HasFlag(FLAGS_::kHasToggledState) || + flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); } /** * 判断当前flutter节点组件是否可显示 @@ -1774,7 +2159,7 @@ bool OhosAccessibilityBridge::IsNodeClickable( bool OhosAccessibilityBridge::IsNodeVisible( flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kIsHidden) ? false : true; + return flutterNode.HasFlag(FLAGS_::kIsHidden) ? false : true; } /** * 判断当前flutter节点组件是否具备checkable属性 @@ -1782,8 +2167,8 @@ bool OhosAccessibilityBridge::IsNodeVisible( bool OhosAccessibilityBridge::IsNodeCheckable( flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kHasCheckedState) || - flutterNode.HasFlag(FLAGS_::kHasToggledState); + return flutterNode.HasFlag(FLAGS_::kHasCheckedState) || + flutterNode.HasFlag(FLAGS_::kHasToggledState); } /** * 判断当前flutter节点组件是否checked/unchecked(checkbox、radio button) @@ -1791,8 +2176,8 @@ bool OhosAccessibilityBridge::IsNodeCheckable( bool OhosAccessibilityBridge::IsNodeChecked( flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kIsChecked) || - flutterNode.HasFlag(FLAGS_::kIsToggled); + return flutterNode.HasFlag(FLAGS_::kIsChecked) || + flutterNode.HasFlag(FLAGS_::kIsToggled); } /** * 判断当前flutter节点组件是否选中 @@ -1800,7 +2185,7 @@ bool OhosAccessibilityBridge::IsNodeChecked( bool OhosAccessibilityBridge::IsNodeSelected( flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kIsSelected); + return flutterNode.HasFlag(FLAGS_::kIsSelected); } /** * 判断当前flutter节点组件是否为密码输入框 @@ -1808,8 +2193,8 @@ bool OhosAccessibilityBridge::IsNodeSelected( bool OhosAccessibilityBridge::IsNodePassword( flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kIsTextField) && - flutterNode.HasFlag(FLAGS_::kIsObscured); + return flutterNode.HasFlag(FLAGS_::kIsTextField) && + flutterNode.HasFlag(FLAGS_::kIsObscured); } /** * 判断当前flutter节点组件是否支持长按功能 @@ -1817,7 +2202,7 @@ bool OhosAccessibilityBridge::IsNodePassword( bool OhosAccessibilityBridge::IsNodeHasLongPress( flutter::SemanticsNode flutterNode) { - return flutterNode.HasAction(ACTIONS_::kLongPress); + return flutterNode.HasAction(ACTIONS_::kLongPress); } /** * 判断当前flutter节点是否enabled @@ -1825,8 +2210,8 @@ bool OhosAccessibilityBridge::IsNodeHasLongPress( bool OhosAccessibilityBridge::IsNodeEnabled( flutter::SemanticsNode flutterNode) { - return !flutterNode.HasFlag(FLAGS_::kHasEnabledState) || - flutterNode.HasFlag(FLAGS_::kIsEnabled); + return !flutterNode.HasFlag(FLAGS_::kHasEnabledState) || + flutterNode.HasFlag(FLAGS_::kIsEnabled); } /** * 判断当前节点是否已经滑动 @@ -1834,7 +2219,7 @@ bool OhosAccessibilityBridge::IsNodeEnabled( bool OhosAccessibilityBridge::HasScrolled( const flutter::SemanticsNode& flutterNode) { - return flutterNode.scrollPosition != std::nan(""); + return flutterNode.scrollPosition != std::nan(""); } /** * 判断是否可滑动 @@ -1842,10 +2227,10 @@ bool OhosAccessibilityBridge::HasScrolled( bool OhosAccessibilityBridge::IsNodeScrollable( flutter::SemanticsNode flutterNode) { - return flutterNode.HasAction(ACTIONS_::kScrollLeft) || - flutterNode.HasAction(ACTIONS_::kScrollRight) || - flutterNode.HasAction(ACTIONS_::kScrollUp) || - flutterNode.HasAction(ACTIONS_::kScrollDown); + return flutterNode.HasAction(ACTIONS_::kScrollLeft) || + flutterNode.HasAction(ACTIONS_::kScrollRight) || + flutterNode.HasAction(ACTIONS_::kScrollUp) || + flutterNode.HasAction(ACTIONS_::kScrollDown); } /** * 判断当前节点组件是否是滑动组件,如: listview, gridview等 @@ -1853,70 +2238,67 @@ bool OhosAccessibilityBridge::IsNodeScrollable( bool OhosAccessibilityBridge::IsScrollableWidget( flutter::SemanticsNode flutterNode) { - return flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); + return flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); } void OhosAccessibilityBridge::AddRouteNodes( std::vector edges, flutter::SemanticsNode node) { - if (node.HasFlag(FLAGS_::kScopesRoute)) { - edges.emplace_back(node); - } - for (auto& childNodeId : node.childrenInTraversalOrder) { - auto childNode = GetFlutterSemanticsNode(childNodeId); - AddRouteNodes(edges, childNode); - } + if (node.HasFlag(FLAGS_::kScopesRoute)) { + edges.emplace_back(node); + } + for (auto& childNodeId : node.childrenInTraversalOrder) { + auto childNode = GetFlutterSemanticsNode(childNodeId); + AddRouteNodes(edges, childNode); + } } std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) { - if (node.HasFlag(FLAGS_::kNamesRoute) && !node.label.empty()) { - return node.label; - } - for (auto& childNodeId : node.childrenInTraversalOrder) { - auto childNode = GetFlutterSemanticsNode(childNodeId); - std::string newName = GetRouteName(childNode); - if (!newName.empty()) { - return newName; + if (node.HasFlag(FLAGS_::kNamesRoute) && !node.label.empty()) { + return node.label; } - } - return ""; + for (auto& childNodeId : node.childrenInTraversalOrder) { + auto childNode = GetFlutterSemanticsNode(childNodeId); + std::string newName = GetRouteName(childNode); + if (!newName.empty()) { + return newName; + } + } + return ""; } void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) { - std::string routeName = GetRouteName(route); - if (routeName.empty()) { - routeName = " "; - } - Flutter_SendAccessibilityAsyncEvent( - static_cast(route.id), - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); + std::string routeName = GetRouteName(route); + if (routeName.empty()) { + routeName = " "; + } + Flutter_SendAccessibilityAsyncEvent( + static_cast(route.id), + ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); } void OhosAccessibilityBridge::removeSemanticsNode( flutter::SemanticsNode nodeToBeRemoved) { - if (!g_flutterSemanticsTree.size()) { - FML_DLOG(ERROR) << "OhosAccessibilityBridge::removeSemanticsNode -> " - "g_flutterSemanticsTree.szie()=0"; - return; - } - if (g_flutterSemanticsTree.find(nodeToBeRemoved.id) == - g_flutterSemanticsTree.end()) { - FML_DLOG(INFO) << "Attempted to remove a node that is not in the tree."; - } - int32_t nodeToBeRemovedParentId = GetParentId(nodeToBeRemoved.id); - for (auto it = g_parentChildIdVec.begin(); it != g_parentChildIdVec.end(); it++) { - if (it->first == nodeToBeRemovedParentId && - it->second == nodeToBeRemoved.id) { - g_parentChildIdVec.erase(it); + if (!g_flutterSemanticsTree.size()) { + FML_DLOG(ERROR) << "OhosAccessibilityBridge::removeSemanticsNode -> " + "g_flutterSemanticsTree.szie()=0"; + return; + } + if (g_flutterSemanticsTree.find(nodeToBeRemoved.id) == + g_flutterSemanticsTree.end()) { + FML_DLOG(INFO) << "Attempted to remove a node that is not in the tree."; + } + int32_t nodeToBeRemovedParentId = GetParentId(nodeToBeRemoved.id); + for (auto it = g_parentChildIdVec.begin(); it != g_parentChildIdVec.end(); it++) { + if (it->first == nodeToBeRemovedParentId && + it->second == nodeToBeRemoved.id) { + g_parentChildIdVec.erase(it); + } } - } - if (nodeToBeRemoved.platformViewId != -1) { - } } /** @@ -1925,11 +2307,11 @@ void OhosAccessibilityBridge::removeSemanticsNode( */ void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() { - g_flutterSemanticsTree.clear(); - g_parentChildIdVec.clear(); - g_screenRectMap.clear(); - g_actions_mp.clear(); - g_flutterNavigationVec.clear(); + g_flutterSemanticsTree.clear(); + g_parentChildIdVec.clear(); + g_screenRectMap.clear(); + g_actions_mp.clear(); + g_flutterNavigationVec.clear(); } /** @@ -1939,166 +2321,166 @@ void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent( flutter::SemanticsNode node) { - SemanticsNodeExtent nodeEx = SemanticsNodeExtent(); - nodeEx.id = std::move(node.id); - nodeEx.flags = std::move(node.flags); - nodeEx.actions = std::move(node.actions); - nodeEx.maxValueLength = std::move(node.maxValueLength); - nodeEx.currentValueLength = std::move(node.currentValueLength); - nodeEx.textSelectionBase = std::move(node.textSelectionBase); - nodeEx.textSelectionExtent = std::move(node.textSelectionExtent); - nodeEx.platformViewId = std::move(node.platformViewId); - nodeEx.scrollChildren = std::move(node.scrollChildren); - nodeEx.scrollIndex = std::move(node.scrollIndex); - nodeEx.scrollPosition = std::move(node.scrollPosition); - nodeEx.scrollExtentMax = std::move(node.scrollExtentMax); - nodeEx.scrollExtentMin = std::move(node.scrollExtentMin); - nodeEx.elevation = std::move(node.elevation); - nodeEx.thickness = std::move(node.thickness); - nodeEx.label = std::move(node.label); - nodeEx.labelAttributes = std::move(node.labelAttributes); - nodeEx.hint = std::move(node.hint); - nodeEx.hintAttributes = std::move(node.hintAttributes); - nodeEx.value = std::move(node.value); - nodeEx.valueAttributes = std::move(node.valueAttributes); - nodeEx.increasedValue = std::move(node.increasedValue); - nodeEx.increasedValueAttributes = std::move(node.increasedValueAttributes); - nodeEx.decreasedValue = std::move(node.decreasedValue); - nodeEx.decreasedValueAttributes = std::move(node.decreasedValueAttributes); - nodeEx.tooltip = std::move(node.tooltip); - nodeEx.textDirection = std::move(node.textDirection); - - nodeEx.rect = std::move(node.rect); - nodeEx.transform = std::move(node.transform); - nodeEx.childrenInTraversalOrder = std::move(node.childrenInTraversalOrder); - nodeEx.childrenInHitTestOrder = std::move(node.childrenInHitTestOrder); - nodeEx.customAccessibilityActions = - std::move(node.customAccessibilityActions); - return nodeEx; + SemanticsNodeExtent nodeEx = SemanticsNodeExtent(); + nodeEx.id = std::move(node.id); + nodeEx.flags = std::move(node.flags); + nodeEx.actions = std::move(node.actions); + nodeEx.maxValueLength = std::move(node.maxValueLength); + nodeEx.currentValueLength = std::move(node.currentValueLength); + nodeEx.textSelectionBase = std::move(node.textSelectionBase); + nodeEx.textSelectionExtent = std::move(node.textSelectionExtent); + nodeEx.platformViewId = std::move(node.platformViewId); + nodeEx.scrollChildren = std::move(node.scrollChildren); + nodeEx.scrollIndex = std::move(node.scrollIndex); + nodeEx.scrollPosition = std::move(node.scrollPosition); + nodeEx.scrollExtentMax = std::move(node.scrollExtentMax); + nodeEx.scrollExtentMin = std::move(node.scrollExtentMin); + nodeEx.elevation = std::move(node.elevation); + nodeEx.thickness = std::move(node.thickness); + nodeEx.label = std::move(node.label); + nodeEx.labelAttributes = std::move(node.labelAttributes); + nodeEx.hint = std::move(node.hint); + nodeEx.hintAttributes = std::move(node.hintAttributes); + nodeEx.value = std::move(node.value); + nodeEx.valueAttributes = std::move(node.valueAttributes); + nodeEx.increasedValue = std::move(node.increasedValue); + nodeEx.increasedValueAttributes = std::move(node.increasedValueAttributes); + nodeEx.decreasedValue = std::move(node.decreasedValue); + nodeEx.decreasedValueAttributes = std::move(node.decreasedValueAttributes); + nodeEx.tooltip = std::move(node.tooltip); + nodeEx.textDirection = std::move(node.textDirection); + + nodeEx.rect = std::move(node.rect); + nodeEx.transform = std::move(node.transform); + nodeEx.childrenInTraversalOrder = std::move(node.childrenInTraversalOrder); + nodeEx.childrenInHitTestOrder = std::move(node.childrenInHitTestOrder); + nodeEx.customAccessibilityActions = + std::move(node.customAccessibilityActions); + return nodeEx; } void OhosAccessibilityBridge::GetSemanticsNodeDebugInfo( flutter::SemanticsNode node) { - FML_DLOG(INFO) << "-------------------SemanticsNode------------------"; - SkMatrix _transform = node.transform.asM33(); - FML_DLOG(INFO) << "node.id=" << node.id; - FML_DLOG(INFO) << "node.label=" << node.label; - FML_DLOG(INFO) << "node.tooltip=" << node.tooltip; - FML_DLOG(INFO) << "node.hint=" << node.hint; - FML_DLOG(INFO) << "node.flags=" << node.flags; - FML_DLOG(INFO) << "node.actions=" << node.actions; - FML_DLOG(INFO) << "node.rect= {" << node.rect.fLeft << ", " << node.rect.fTop - << ", " << node.rect.fRight << ", " << node.rect.fBottom - << "}"; - FML_DLOG(INFO) << "node.transform -> kMScaleX=" - << _transform.get(SkMatrix::kMScaleX); - FML_DLOG(INFO) << "node.transform -> kMSkewX=" - << _transform.get(SkMatrix::kMSkewX); - FML_DLOG(INFO) << "node.transform -> kMTransX=" - << _transform.get(SkMatrix::kMTransX); - FML_DLOG(INFO) << "node.transform -> kMSkewY=" - << _transform.get(SkMatrix::kMSkewY); - FML_DLOG(INFO) << "node.transform -> kMScaleY=" - << _transform.get(SkMatrix::kMScaleY); - FML_DLOG(INFO) << "node.transform -> kMTransY=" - << _transform.get(SkMatrix::kMTransY); - FML_DLOG(INFO) << "node.transform -> kMPersp0=" - << _transform.get(SkMatrix::kMPersp0); - FML_DLOG(INFO) << "node.transform -> kMPersp1=" - << _transform.get(SkMatrix::kMPersp1); - FML_DLOG(INFO) << "node.transform -> kMPersp2=" - << _transform.get(SkMatrix::kMPersp2); - FML_DLOG(INFO) << "node.maxValueLength=" << node.maxValueLength; - FML_DLOG(INFO) << "node.currentValueLength=" << node.currentValueLength; - FML_DLOG(INFO) << "node.textSelectionBase=" << node.textSelectionBase; - FML_DLOG(INFO) << "node.textSelectionExtent=" << node.textSelectionExtent; - FML_DLOG(INFO) << "node.textSelectionBase=" << node.textSelectionBase; - FML_DLOG(INFO) << "node.platformViewId=" << node.platformViewId; - FML_DLOG(INFO) << "node.scrollChildren=" << node.scrollChildren; - FML_DLOG(INFO) << "node.scrollIndex=" << node.scrollIndex; - FML_DLOG(INFO) << "node.scrollPosition=" << node.scrollPosition; - FML_DLOG(INFO) << "node.scrollIndex=" << node.scrollIndex; - FML_DLOG(INFO) << "node.scrollPosition=" << node.scrollPosition; - FML_DLOG(INFO) << "node.scrollExtentMax=" << node.scrollExtentMax; - FML_DLOG(INFO) << "node.scrollExtentMin=" << node.scrollExtentMin; - FML_DLOG(INFO) << "node.elevation=" << node.elevation; - FML_DLOG(INFO) << "node.thickness=" << node.thickness; - FML_DLOG(INFO) << "node.textDirection=" << node.textDirection; - FML_DLOG(INFO) << "node.childrenInTraversalOrder.size()=" - << node.childrenInTraversalOrder.size(); - for (uint32_t i = 0; i < node.childrenInTraversalOrder.size(); i++) { - FML_DLOG(INFO) << "node.childrenInTraversalOrder[" << i - << "]=" << node.childrenInTraversalOrder[i]; - } - FML_DLOG(INFO) << "node.childrenInHitTestOrder.size()=" - << node.childrenInHitTestOrder.size(); - for (uint32_t i = 0; i < node.childrenInHitTestOrder.size(); i++) { - FML_DLOG(INFO) << "node.childrenInHitTestOrder[" << i - << "]=" << node.childrenInHitTestOrder[i]; - } - FML_DLOG(INFO) << "node.customAccessibilityActions.size()=" - << node.customAccessibilityActions.size(); - for (uint32_t i = 0; i < node.customAccessibilityActions.size(); i++) { - FML_DLOG(INFO) << "node.customAccessibilityActions[" << i - << "]=" << node.customAccessibilityActions[i]; - } - FML_DLOG(INFO) << "------------------SemanticsNode-----------------"; + FML_DLOG(INFO) << "-------------------SemanticsNode------------------"; + SkMatrix _transform = node.transform.asM33(); + FML_DLOG(INFO) << "node.id=" << node.id; + FML_DLOG(INFO) << "node.label=" << node.label; + FML_DLOG(INFO) << "node.tooltip=" << node.tooltip; + FML_DLOG(INFO) << "node.hint=" << node.hint; + FML_DLOG(INFO) << "node.flags=" << node.flags; + FML_DLOG(INFO) << "node.actions=" << node.actions; + FML_DLOG(INFO) << "node.rect= {" << node.rect.fLeft << ", " << node.rect.fTop + << ", " << node.rect.fRight << ", " << node.rect.fBottom + << "}"; + FML_DLOG(INFO) << "node.transform -> kMScaleX=" + << _transform.get(SkMatrix::kMScaleX); + FML_DLOG(INFO) << "node.transform -> kMSkewX=" + << _transform.get(SkMatrix::kMSkewX); + FML_DLOG(INFO) << "node.transform -> kMTransX=" + << _transform.get(SkMatrix::kMTransX); + FML_DLOG(INFO) << "node.transform -> kMSkewY=" + << _transform.get(SkMatrix::kMSkewY); + FML_DLOG(INFO) << "node.transform -> kMScaleY=" + << _transform.get(SkMatrix::kMScaleY); + FML_DLOG(INFO) << "node.transform -> kMTransY=" + << _transform.get(SkMatrix::kMTransY); + FML_DLOG(INFO) << "node.transform -> kMPersp0=" + << _transform.get(SkMatrix::kMPersp0); + FML_DLOG(INFO) << "node.transform -> kMPersp1=" + << _transform.get(SkMatrix::kMPersp1); + FML_DLOG(INFO) << "node.transform -> kMPersp2=" + << _transform.get(SkMatrix::kMPersp2); + FML_DLOG(INFO) << "node.maxValueLength=" << node.maxValueLength; + FML_DLOG(INFO) << "node.currentValueLength=" << node.currentValueLength; + FML_DLOG(INFO) << "node.textSelectionBase=" << node.textSelectionBase; + FML_DLOG(INFO) << "node.textSelectionExtent=" << node.textSelectionExtent; + FML_DLOG(INFO) << "node.textSelectionBase=" << node.textSelectionBase; + FML_DLOG(INFO) << "node.platformViewId=" << node.platformViewId; + FML_DLOG(INFO) << "node.scrollChildren=" << node.scrollChildren; + FML_DLOG(INFO) << "node.scrollIndex=" << node.scrollIndex; + FML_DLOG(INFO) << "node.scrollPosition=" << node.scrollPosition; + FML_DLOG(INFO) << "node.scrollIndex=" << node.scrollIndex; + FML_DLOG(INFO) << "node.scrollPosition=" << node.scrollPosition; + FML_DLOG(INFO) << "node.scrollExtentMax=" << node.scrollExtentMax; + FML_DLOG(INFO) << "node.scrollExtentMin=" << node.scrollExtentMin; + FML_DLOG(INFO) << "node.elevation=" << node.elevation; + FML_DLOG(INFO) << "node.thickness=" << node.thickness; + FML_DLOG(INFO) << "node.textDirection=" << node.textDirection; + FML_DLOG(INFO) << "node.childrenInTraversalOrder.size()=" + << node.childrenInTraversalOrder.size(); + for (uint32_t i = 0; i < node.childrenInTraversalOrder.size(); i++) { + FML_DLOG(INFO) << "node.childrenInTraversalOrder[" << i + << "]=" << node.childrenInTraversalOrder[i]; + } + FML_DLOG(INFO) << "node.childrenInHitTestOrder.size()=" + << node.childrenInHitTestOrder.size(); + for (uint32_t i = 0; i < node.childrenInHitTestOrder.size(); i++) { + FML_DLOG(INFO) << "node.childrenInHitTestOrder[" << i + << "]=" << node.childrenInHitTestOrder[i]; + } + FML_DLOG(INFO) << "node.customAccessibilityActions.size()=" + << node.customAccessibilityActions.size(); + for (uint32_t i = 0; i < node.customAccessibilityActions.size(); i++) { + FML_DLOG(INFO) << "node.customAccessibilityActions[" << i + << "]=" << node.customAccessibilityActions[i]; + } + FML_DLOG(INFO) << "------------------SemanticsNode-----------------"; } void OhosAccessibilityBridge::GetSemanticsFlagsDebugInfo( flutter::SemanticsNode node) { - FML_DLOG(INFO) << "----------------SemanticsFlags-------------------------"; - FML_DLOG(INFO) << "node.id=" << node.id; - FML_DLOG(INFO) << "node.label=" << node.label; - FML_DLOG(INFO) << "kHasCheckedState: " - << node.HasFlag(FLAGS_::kHasCheckedState); - FML_DLOG(INFO) << "kIsChecked:" << node.HasFlag(FLAGS_::kIsChecked); - FML_DLOG(INFO) << "kIsSelected:" << node.HasFlag(FLAGS_::kIsSelected); - FML_DLOG(INFO) << "kIsButton:" << node.HasFlag(FLAGS_::kIsButton); - FML_DLOG(INFO) << "kIsTextField:" << node.HasFlag(FLAGS_::kIsTextField); - FML_DLOG(INFO) << "kIsFocused:" << node.HasFlag(FLAGS_::kIsFocused); - FML_DLOG(INFO) << "kHasEnabledState:" - << node.HasFlag(FLAGS_::kHasEnabledState); - FML_DLOG(INFO) << "kIsEnabled:" << node.HasFlag(FLAGS_::kIsEnabled); - FML_DLOG(INFO) << "kIsInMutuallyExclusiveGroup:" - << node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup); - FML_DLOG(INFO) << "kIsHeader:" << node.HasFlag(FLAGS_::kIsHeader); - FML_DLOG(INFO) << "kIsObscured:" << node.HasFlag(FLAGS_::kIsObscured); - FML_DLOG(INFO) << "kScopesRoute:" << node.HasFlag(FLAGS_::kScopesRoute); - FML_DLOG(INFO) << "kNamesRoute:" << node.HasFlag(FLAGS_::kNamesRoute); - FML_DLOG(INFO) << "kIsHidden:" << node.HasFlag(FLAGS_::kIsHidden); - FML_DLOG(INFO) << "kIsImage:" << node.HasFlag(FLAGS_::kIsImage); - FML_DLOG(INFO) << "kIsLiveRegion:" << node.HasFlag(FLAGS_::kIsLiveRegion); - FML_DLOG(INFO) << "kHasToggledState:" - << node.HasFlag(FLAGS_::kHasToggledState); - FML_DLOG(INFO) << "kIsToggled:" << node.HasFlag(FLAGS_::kIsToggled); - FML_DLOG(INFO) << "kHasImplicitScrolling:" - << node.HasFlag(FLAGS_::kHasImplicitScrolling); - FML_DLOG(INFO) << "kIsMultiline:" << node.HasFlag(FLAGS_::kIsMultiline); - FML_DLOG(INFO) << "kIsReadOnly:" << node.HasFlag(FLAGS_::kIsReadOnly); - FML_DLOG(INFO) << "kIsFocusable:" << node.HasFlag(FLAGS_::kIsFocusable); - FML_DLOG(INFO) << "kIsLink:" << node.HasFlag(FLAGS_::kIsLink); - FML_DLOG(INFO) << "kIsSlider:" << node.HasFlag(FLAGS_::kIsSlider); - FML_DLOG(INFO) << "kIsKeyboardKey:" << node.HasFlag(FLAGS_::kIsKeyboardKey); - FML_DLOG(INFO) << "kIsCheckStateMixed:" - << node.HasFlag(FLAGS_::kIsCheckStateMixed); - FML_DLOG(INFO) << "----------------SemanticsFlags--------------------"; -} - -void OhosAccessibilityBridge::GetCustomActionDebugInfo( - flutter::CustomAccessibilityAction customAccessibilityAction) -{ - FML_DLOG(INFO) << "--------------CustomAccessibilityAction------------"; - FML_DLOG(INFO) << "customAccessibilityAction.id=" - << customAccessibilityAction.id; - FML_DLOG(INFO) << "customAccessibilityAction.overrideId=" - << customAccessibilityAction.overrideId; - FML_DLOG(INFO) << "customAccessibilityAction.label=" - << customAccessibilityAction.label; - FML_DLOG(INFO) << "customAccessibilityAction.hint=" - << customAccessibilityAction.hint; - FML_DLOG(INFO) << "------------CustomAccessibilityAction--------------"; + FML_DLOG(INFO) << "----------------SemanticsFlags-------------------------"; + FML_DLOG(INFO) << "node.id=" << node.id; + FML_DLOG(INFO) << "node.label=" << node.label; + FML_DLOG(INFO) << "kHasCheckedState: " + << node.HasFlag(FLAGS_::kHasCheckedState); + FML_DLOG(INFO) << "kIsChecked:" << node.HasFlag(FLAGS_::kIsChecked); + FML_DLOG(INFO) << "kIsSelected:" << node.HasFlag(FLAGS_::kIsSelected); + FML_DLOG(INFO) << "kIsButton:" << node.HasFlag(FLAGS_::kIsButton); + FML_DLOG(INFO) << "kIsTextField:" << node.HasFlag(FLAGS_::kIsTextField); + FML_DLOG(INFO) << "kIsFocused:" << node.HasFlag(FLAGS_::kIsFocused); + FML_DLOG(INFO) << "kHasEnabledState:" + << node.HasFlag(FLAGS_::kHasEnabledState); + FML_DLOG(INFO) << "kIsEnabled:" << node.HasFlag(FLAGS_::kIsEnabled); + FML_DLOG(INFO) << "kIsInMutuallyExclusiveGroup:" + << node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup); + FML_DLOG(INFO) << "kIsHeader:" << node.HasFlag(FLAGS_::kIsHeader); + FML_DLOG(INFO) << "kIsObscured:" << node.HasFlag(FLAGS_::kIsObscured); + FML_DLOG(INFO) << "kScopesRoute:" << node.HasFlag(FLAGS_::kScopesRoute); + FML_DLOG(INFO) << "kNamesRoute:" << node.HasFlag(FLAGS_::kNamesRoute); + FML_DLOG(INFO) << "kIsHidden:" << node.HasFlag(FLAGS_::kIsHidden); + FML_DLOG(INFO) << "kIsImage:" << node.HasFlag(FLAGS_::kIsImage); + FML_DLOG(INFO) << "kIsLiveRegion:" << node.HasFlag(FLAGS_::kIsLiveRegion); + FML_DLOG(INFO) << "kHasToggledState:" + << node.HasFlag(FLAGS_::kHasToggledState); + FML_DLOG(INFO) << "kIsToggled:" << node.HasFlag(FLAGS_::kIsToggled); + FML_DLOG(INFO) << "kHasImplicitScrolling:" + << node.HasFlag(FLAGS_::kHasImplicitScrolling); + FML_DLOG(INFO) << "kIsMultiline:" << node.HasFlag(FLAGS_::kIsMultiline); + FML_DLOG(INFO) << "kIsReadOnly:" << node.HasFlag(FLAGS_::kIsReadOnly); + FML_DLOG(INFO) << "kIsFocusable:" << node.HasFlag(FLAGS_::kIsFocusable); + FML_DLOG(INFO) << "kIsLink:" << node.HasFlag(FLAGS_::kIsLink); + FML_DLOG(INFO) << "kIsSlider:" << node.HasFlag(FLAGS_::kIsSlider); + FML_DLOG(INFO) << "kIsKeyboardKey:" << node.HasFlag(FLAGS_::kIsKeyboardKey); + FML_DLOG(INFO) << "kIsCheckStateMixed:" + << node.HasFlag(FLAGS_::kIsCheckStateMixed); + FML_DLOG(INFO) << "----------------SemanticsFlags--------------------"; + } + + void OhosAccessibilityBridge::GetCustomActionDebugInfo( + flutter::CustomAccessibilityAction customAccessibilityAction) + { + FML_DLOG(INFO) << "--------------CustomAccessibilityAction------------"; + FML_DLOG(INFO) << "customAccessibilityAction.id=" + << customAccessibilityAction.id; + FML_DLOG(INFO) << "customAccessibilityAction.overrideId=" + << customAccessibilityAction.overrideId; + FML_DLOG(INFO) << "customAccessibilityAction.label=" + << customAccessibilityAction.label; + FML_DLOG(INFO) << "customAccessibilityAction.hint=" + << customAccessibilityAction.hint; + FML_DLOG(INFO) << "------------CustomAccessibilityAction--------------"; } } // namespace flutter diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index def86d8701..5f03fdc839 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -14,17 +14,19 @@ */ #ifndef OHOS_ACCESSIBILITY_BRIDGE_H #define OHOS_ACCESSIBILITY_BRIDGE_H -#include #include #include #include #include #include +#include #include "flutter/fml/mapping.h" #include "flutter/lib/ui/semantics/custom_accessibility_action.h" #include "flutter/lib/ui/semantics/semantics_node.h" #include "native_accessibility_channel.h" #include "ohos_accessibility_features.h" +#include "ohos_accessibility_ddl.h" + namespace flutter { typedef flutter::SemanticsFlags FLAGS_; typedef flutter::SemanticsAction ACTIONS_; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_ddl.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_ddl.cpp new file mode 100644 index 0000000000..39ea57e8a9 --- /dev/null +++ b/shell/platform/ohos/accessibility/ohos_accessibility_ddl.cpp @@ -0,0 +1,287 @@ +/* + * 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 "ohos_accessibility_ddl.h" + +namespace flutter { + +OhosAccessibilityDDL::OhosAccessibilityDDL() = default; +OhosAccessibilityDDL::~OhosAccessibilityDDL() = default; + +RegisterFunc OhosAccessibilityDDL::DLLoadRegisterFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} + +SendAsyncEventFunc OhosAccessibilityDDL::DLLoadSendAsyncEventFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} + +GetElemFunc OhosAccessibilityDDL::DLLoadGetElemFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} + +CreateElemInfoFunc OhosAccessibilityDDL::DLLoadCreateElemInfoFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} + +CreateEventInfoFunc OhosAccessibilityDDL::DLLoadCreateEventInfoFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} + +DestroyElemFunc OhosAccessibilityDDL::DLLoadDestroyElemFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} + +DestroyEventFunc OhosAccessibilityDDL::DLLoadDestroyEventFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} + + +SetElemIntFunc OhosAccessibilityDDL::DLLoadSetElemIntFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} +SetElemStringFunc OhosAccessibilityDDL::DLLoadSetElemStringFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} +SetElemBoolFunc OhosAccessibilityDDL::DLLoadSetElemBoolFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} +SetElemChildFunc OhosAccessibilityDDL::DLLoadSetElemChildFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} + + +SetElemOperActionsFunc OhosAccessibilityDDL::DLLoadSetElemOperActionsFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} +SetElemSreenRectFunc OhosAccessibilityDDL::DLLoadSetElemSreenRectFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} +SetEventFunc OhosAccessibilityDDL::DLLoadSetEventFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} +SetEventElemFunc OhosAccessibilityDDL::DLLoadSetEventElemFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} + +SetReqFocusFunc OhosAccessibilityDDL::DLLoadSetReqFocusFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} + +SetEventStringFunc OhosAccessibilityDDL::DLLoadSetEventStringFunc(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} + +GetNativeA11yProvider OhosAccessibilityDDL::DLLoadGetNativeA11yProvider(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} +} \ No newline at end of file diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_ddl.h b/shell/platform/ohos/accessibility/ohos_accessibility_ddl.h new file mode 100644 index 0000000000..c5d6c32631 --- /dev/null +++ b/shell/platform/ohos/accessibility/ohos_accessibility_ddl.h @@ -0,0 +1,82 @@ +/* + * 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 OHOS_ACCESSIBILITY_DDL_H +#define OHOS_ACCESSIBILITY_DDL_H +#include +#include +#include "flutter/shell/platform/ohos/utils/ddl_utils.h" + +namespace flutter { + +using RegisterFunc = int32_t (*)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityProviderCallbacks*); +using SendAsyncEventFunc = void (*)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*)(int32_t)); +using GetElemFunc = ArkUI_AccessibilityElementInfo* (*)(ArkUI_AccessibilityElementInfoList*); + +using CreateElemInfoFunc = ArkUI_AccessibilityElementInfo* (*)(void); +using CreateEventInfoFunc = ArkUI_AccessibilityEventInfo* (*)(void); +using DestroyElemFunc = void (*)(ArkUI_AccessibilityElementInfo*); +using DestroyEventFunc = void (*)(ArkUI_AccessibilityEventInfo*); + +using SetElemIntFunc = int32_t (*)(ArkUI_AccessibilityElementInfo*, int32_t); +using SetElemStringFunc = int32_t (*)(ArkUI_AccessibilityElementInfo*, const char*); +using SetEventStringFunc = int32_t (*)(ArkUI_AccessibilityEventInfo*, const char*); +using SetElemBoolFunc = int32_t (*)(ArkUI_AccessibilityElementInfo*, bool); +using SetElemChildFunc = int32_t (*)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*); + +using SetElemOperActionsFunc = int32_t (*)(ArkUI_AccessibilityElementInfo*, int32_t, ArkUI_AccessibleAction*); +using SetElemSreenRectFunc = int32_t (*)(ArkUI_AccessibilityElementInfo*, ArkUI_AccessibleRect*); +using SetEventFunc = int32_t (*)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType); +using SetEventElemFunc = int32_t (*)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityElementInfo*); + +using SetReqFocusFunc = int32_t (*)(ArkUI_AccessibilityEventInfo*, int32_t); +using GetNativeA11yProvider = int32_t (*)(OH_NativeXComponent*, ArkUI_AccessibilityProvider**); + +class OhosAccessibilityDDL { +public: + OhosAccessibilityDDL(); + ~OhosAccessibilityDDL(); + + static constexpr char ACCESSIBILITY_LIB_NAME[] = "libflutter_accessibility.so"; + + static RegisterFunc DLLoadRegisterFunc(const char* symbolName); + static SendAsyncEventFunc DLLoadSendAsyncEventFunc(const char* symbolName); + static GetElemFunc DLLoadGetElemFunc(const char* symbolName); + + static CreateElemInfoFunc DLLoadCreateElemInfoFunc(const char* symbolName); + static CreateEventInfoFunc DLLoadCreateEventInfoFunc(const char* symbolName); + static DestroyElemFunc DLLoadDestroyElemFunc(const char* symbolName); + static DestroyEventFunc DLLoadDestroyEventFunc(const char* symbolName); + + static SetElemIntFunc DLLoadSetElemIntFunc(const char* symbolName); + static SetElemStringFunc DLLoadSetElemStringFunc(const char* symbolName); + static SetEventStringFunc DLLoadSetEventStringFunc(const char* symbolName); + static SetElemBoolFunc DLLoadSetElemBoolFunc(const char* symbolName); + static SetElemChildFunc DLLoadSetElemChildFunc(const char* symbolName); + + static SetElemOperActionsFunc DLLoadSetElemOperActionsFunc(const char* symbolName); + static SetElemSreenRectFunc DLLoadSetElemSreenRectFunc(const char* symbolName); + static SetEventFunc DLLoadSetEventFunc(const char* symbolName); + static SetEventElemFunc DLLoadSetEventElemFunc(const char* symbolName); + static SetReqFocusFunc DLLoadSetReqFocusFunc(const char* symbolName); + + static GetNativeA11yProvider DLLoadGetNativeA11yProvider(const char* symbolName); + + +}; + + +} // namespace flutter + +#endif \ No newline at end of file diff --git a/shell/platform/ohos/compatibility/ohos_accessibility_interface.h b/shell/platform/ohos/compatibility/ohos_accessibility_interface.h new file mode 100644 index 0000000000..5a4ca0769d --- /dev/null +++ b/shell/platform/ohos/compatibility/ohos_accessibility_interface.h @@ -0,0 +1,703 @@ +/* + * 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. + */ + +/** + * @addtogroup ArkUI_Accessibility + * @{ + * + * @brief Describes the native capabilities supported by ArkUI Accessibility, such as querying accessibility nodes and + * reporting accessibility events. + * + * @since 13 + */ + +/** + * @file native_interface_accessibility.h + * + * @brief Declares the APIs used to access the native Accessibility. + * + * @library libace_ndk.z.so + * @syscap SystemCapability.ArkUI.ArkUI.Full + * @kit ArkUI + * @since 13 + */ +#ifndef OHOS_ACCESSIBILITY_INTERFACE_H +#define OHOS_ACCESSIBILITY_INTERFACE_H + +#include +#include +#ifdef __cplusplus +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Obtains the pointer to the ArkUI_AccessibilityProvider + * instance of this OH_NativeXComponent instance. + * + * @param component Indicates the pointer to the OH_NativeXComponent instance. + * @param handle Indicates the pointer to the ArkUI_AccessibilityProvider instance. + * @return Returns {@link OH_NATIVEXCOMPONENT_RESULT_SUCCESS} if the operation is successful. + * Returns {@link OH_NATIVEXCOMPONENT_RESULT_BAD_PARAMETER} if a parameter error occurs. + * @since 13 + */ +int32_t OH_NativeXComponent_GetNativeAccessibilityProvider( + OH_NativeXComponent* component, ArkUI_AccessibilityProvider** handle); + +/** + * @brief Registers a callback for this ArkUI_AccessibilityProvider instance. + * + * @param provider Indicates the pointer to the ArkUI_AccessibilityProvider instance. + * @param callbacks Indicates the pointer to the GetAccessibilityNodeCursorPosition callback. + * @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. + * Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. + * @since 13 + */ +int32_t OH_ArkUI_AccessibilityProviderRegisterCallback( + ArkUI_AccessibilityProvider* provider, ArkUI_AccessibilityProviderCallbacks* callbacks); + +/** + * @brief Sends accessibility event information. + * + * @param provider Indicates the pointer to the ArkUI_AccessibilityProvider instance. + * @param eventInfo Indicates the pointer to the accessibility event information. + * @param callback Indicates the pointer to the callback that is called after the event is sent. + * @since 13 + */ +void OH_ArkUI_SendAccessibilityAsyncEvent( + ArkUI_AccessibilityProvider* provider, ArkUI_AccessibilityEventInfo* eventInfo, + void (*callback)(int32_t errorCode)); + +/** + * @brief Adds and obtains the pointer to an ArkUI_AccessibilityElementInfo object. + * + * @param list Indicates the pointer to an ArkUI_AccessibilityElementInfoList object. + * @return Returns the pointer to the ArkUI_AccessibilityElementInfo object. + * @since 13 + */ +ArkUI_AccessibilityElementInfo* OH_ArkUI_AddAndGetAccessibilityElementInfo( + ArkUI_AccessibilityElementInfoList* list); + +/** +* @brief Sets the element ID for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param elementId Indicates the element ID. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetElementId( + ArkUI_AccessibilityElementInfo* elementInfo, int32_t elementId); + +/** +* @brief Sets the parent ID for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param parentId Indicates the parent ID. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetParentId( + ArkUI_AccessibilityElementInfo* elementInfo, int32_t parentId); + +/** +* @brief Sets the component type for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param componentType Indicates the component type. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetComponentType( + ArkUI_AccessibilityElementInfo* elementInfo, const char* componentType); + +/** +* @brief Sets the component content for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param contents Indicates the component content. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetContents( + ArkUI_AccessibilityElementInfo* elementInfo, const char* contents); + +/** +* @brief Sets the hint text for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param hintText Indicates the hint text. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetHintText( + ArkUI_AccessibilityElementInfo* elementInfo, const char* hintText); + +/** +* @brief Sets the accessibility text for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param accessibilityText Indicates the accessibility text. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( + ArkUI_AccessibilityElementInfo* elementInfo, const char* accessibilityText); + +/** +* @brief Sets the accessibility description for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param accessibilityDescription Indicates the accessibility description. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetAccessibilityDescription( + ArkUI_AccessibilityElementInfo* elementInfo, const char* accessibilityDescription); + +/** +* @brief Set the number of child nodes and child node IDs for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param childCount Indicates the number of child nodes. +* @param childNodeIds Indicates an array of child node IDs. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetChildNodeIds( + ArkUI_AccessibilityElementInfo* elementInfo, int32_t childCount, int64_t* childNodeIds); + +/** +* @brief Sets the operation actions for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param operationCount Indicates the operation count. +* @param operationActions Indicates the operation actions. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetOperationActions(ArkUI_AccessibilityElementInfo* elementInfo, + int32_t operationCount, ArkUI_AccessibleAction* operationActions); + +/** +* @brief Sets the screen area for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param screenRect Indicates the screen area. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetScreenRect( + ArkUI_AccessibilityElementInfo* elementInfo, ArkUI_AccessibleRect* screenRect); + +/** +* @brief Sets whether the element is checkable for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param checkable Indicates whether the element is checkable. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetCheckable( + ArkUI_AccessibilityElementInfo* elementInfo, bool checkable); + +/** +* @brief Sets whether the element is checked for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param checked Indicates whether the element is checked. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetChecked( + ArkUI_AccessibilityElementInfo* elementInfo, bool checked); + +/** +* @brief Sets whether the element is focusable for an ArkUI_AccessibilityElementInfo object. +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param focusable Indicates whether the element is focusable. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetFocusable( + ArkUI_AccessibilityElementInfo* elementInfo, bool focusable); + +/** +* @brief Sets whether the element is focused for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param isFocused Indicates whether the element is focused. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetFocused( + ArkUI_AccessibilityElementInfo* elementInfo, bool isFocused); + +/** +* @brief Sets whether the element is visible for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param isVisible Indicates whether the element is visible. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetVisible( + ArkUI_AccessibilityElementInfo* elementInfo, bool isVisible); + +/** +* @brief Sets the accessibility focus state for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param accessibilityFocused Indicates whether the element has accessibility focus. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused( + ArkUI_AccessibilityElementInfo* elementInfo, bool accessibilityFocused); + +/** +* @brief Sets whether the element is selected for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param selected Indicates whether the element is selected. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetSelected( + ArkUI_AccessibilityElementInfo* elementInfo, bool selected); + +/** +* @brief Sets whether the element is clickable for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param clickable Indicates whether the element is clickable. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetClickable( + ArkUI_AccessibilityElementInfo* elementInfo, bool clickable); + +/** +* @brief Sets whether the element is long clickable for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param longClickable Indicates whether the element is long clickable. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetLongClickable( + ArkUI_AccessibilityElementInfo* elementInfo, bool longClickable); + +/** +* @brief Sets whether the element is enabled for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param isEnabled Indicates whether the element is enabled. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetEnabled( + ArkUI_AccessibilityElementInfo* elementInfo, bool isEnabled); + +/** +* @brief Sets whether the element is a password for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param isPassword Indicates whether the element is a password. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetIsPassword( + ArkUI_AccessibilityElementInfo* elementInfo, bool isPassword); + +/** +* @brief Sets whether the element is scrollable for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param scrollable Indicates whether the element is scrollable. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetScrollable( + ArkUI_AccessibilityElementInfo* elementInfo, bool scrollable); + +/** +* @brief Sets whether the element is editable for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param editable Indicates whether the element is editable. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetEditable( + ArkUI_AccessibilityElementInfo* elementInfo, bool editable); + +/** +* @brief Sets whether the element is a hint for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param isHint Indicates whether the element is a hint. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetIsHint( + ArkUI_AccessibilityElementInfo* elementInfo, bool isHint); + +/** +* @brief Sets the range information for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param rangeInfo Indicates the range information. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetRangeInfo( + ArkUI_AccessibilityElementInfo* elementInfo, ArkUI_AccessibleRangeInfo* rangeInfo); + +/** +* @brief Sets the grid information for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param gridInfo Indicates the grid information. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetGridInfo( + ArkUI_AccessibilityElementInfo* elementInfo, ArkUI_AccessibleGridInfo* gridInfo); + +/** +* @brief Sets the grid item for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param gridItem Indicates the grid item. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetGridItemInfo( + ArkUI_AccessibilityElementInfo* elementInfo, ArkUI_AccessibleGridItemInfo* gridItem); + +/** +* @brief Sets the starting index of the selected text for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param selectedTextStart Indicates the starting index of the selected text +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetSelectedTextStart( + ArkUI_AccessibilityElementInfo* elementInfo, int32_t selectedTextStart); + +/** +* @brief Sets the end index of the selected text for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param selectedTextEnd Indicates the end index of the selected text +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetSelectedTextEnd( + ArkUI_AccessibilityElementInfo* elementInfo, int32_t selectedTextEnd); + +/** +* @brief Sets the index of the currently selected item for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param currentItemIndex Indicates the index of the currently selected item. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex( + ArkUI_AccessibilityElementInfo* elementInfo, int32_t currentItemIndex); + +/** +* @brief Sets the index of the first item for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param startItemIndex Indicates the index of the first item. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetStartItemIndex( + ArkUI_AccessibilityElementInfo* elementInfo, int32_t startItemIndex); + +/** +* @brief Sets the index of the last item for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param endItemIndex Indicates the index of the last item. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetEndItemIndex( + ArkUI_AccessibilityElementInfo* elementInfo, int32_t endItemIndex); + +/** +* @brief Sets the number of items for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param itemCount Indicates the number of items. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetItemCount( + ArkUI_AccessibilityElementInfo* elementInfo, int32_t itemCount); + +/** +* @brief Sets the offset for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param offset Indicates the scroll pixel offset relative to the top of the element. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetAccessibilityOffset( + ArkUI_AccessibilityElementInfo* elementInfo, int32_t offset); + +/** +* @brief Sets the accessibility group for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param accessibilityGroup Indicates the accessibility group. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup( + ArkUI_AccessibilityElementInfo* elementInfo, bool accessibilityGroup); + +/** +* @brief Sets the accessibility level for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param accessibilityLevel Indicates the accessibility level. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel( + ArkUI_AccessibilityElementInfo* elementInfo, const char* accessibilityLevel); + +/** +* @brief Sets the z-index for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param zIndex Indicates the z-index value. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetZIndex( + ArkUI_AccessibilityElementInfo* elementInfo, int32_t zIndex); + +/** +* @brief Sets the opacity for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param opacity Indicates the opacity. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetAccessibilityOpacity( + ArkUI_AccessibilityElementInfo* elementInfo, float opacity); + +/** +* @brief Sets the background color for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param backgroundColor Indicates the background color. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetBackgroundColor( + ArkUI_AccessibilityElementInfo* elementInfo, const char* backgroundColor); + +/** +* @brief Sets the background image for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param backgroundImage Indicates the backgroundImage. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetBackgroundImage( + ArkUI_AccessibilityElementInfo* elementInfo, const char* backgroundImage); + +/** +* @brief Sets the blur effect for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param blur Indicates the blur effect. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetBlur( + ArkUI_AccessibilityElementInfo* elementInfo, const char* blur); + +/** +* @brief Sets the hit test behavior for an ArkUI_AccessibilityElementInfo object. +* +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @param hitTestBehavior Indicates the hit test behavior. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityElementInfoSetHitTestBehavior( + ArkUI_AccessibilityElementInfo* elementInfo, const char* hitTestBehavior); + +/** + * @brief Creates an ArkUI_AccessibilityElementInfo object. + * + * @return Returns the ArkUI_AccessibilityElementInfo object, or NULL if it fails to create. + * The possible reason for failure is that the memory error occurred during object creation. + * @since 13 + * @version 1.0 + */ +ArkUI_AccessibilityElementInfo* OH_ArkUI_CreateAccessibilityElementInfo(void); + +/** + * @brief Destroys an ArkUI_AccessibilityElementInfo object. + * + * @param elementInfo Indicates the pointer to the ArkUI_AccessibilityElementInfo object to destroy. + * @since 13 + * @version 1.0 + */ +void OH_ArkUI_DestoryAccessibilityElementInfo(ArkUI_AccessibilityElementInfo* elementInfo); + +/** + * @brief Creates an ArkUI_AccessibilityEventInfo object. + * + * @return Returns the ArkUI_AccessibilityEventInfo object, or NULL if it fails to create. + * The possible reason for failure is that the memory error occurred during object creation. + * @since 13 + */ +ArkUI_AccessibilityEventInfo* OH_ArkUI_CreateAccessibilityEventInfo(void); + +/** + * @brief Destroys an ArkUI_AccessibilityEventInfo object. + * + * @param eventInfo Indicates the pointer to the ArkUI_AccessibilityEventInfo object to destroy. + * @since 13 + */ +void OH_ArkUI_DestoryAccessibilityEventInfo(ArkUI_AccessibilityEventInfo* eventInfo); + +/** +* @brief Sets the event type for an ArkUI_AccessibilityEventInfo object. +* +* @param eventInfo Indicates the pointer to an ArkUI_AccessibilityEventInfo object. +* @param eventType Indicates the event type. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityEventSetEventType( + ArkUI_AccessibilityEventInfo* eventInfo, ArkUI_AccessibilityEventType eventType); + +/** +* @brief Sets the text announced for accessibility for an ArkUI_AccessibilityEventInfo object. +* +* @param eventInfo Indicates the pointer to an ArkUI_AccessibilityEventInfo object. +* @param textAnnouncedForAccessibility Indicates the text announced for accessibility. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility( + ArkUI_AccessibilityEventInfo* eventInfo, const char* textAnnouncedForAccessibility); + +/** +* @brief Sets the request focus ID for an ArkUI_AccessibilityEventInfo object. +* +* @param eventInfo Indicates the pointer to an ArkUI_AccessibilityEventInfo object. +* @param requestFocusId Indicates the request focus ID. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityEventSetRequestFocusId( + ArkUI_AccessibilityEventInfo* eventInfo, int32_t requestFocusId); + +/** +* @brief Sets the element information for an ArkUI_AccessibilityEventInfo object. +* +* @param eventInfo Indicates the pointer to an ArkUI_AccessibilityEventInfo object. +* @param elementInfo Indicates the pointer to an ArkUI_AccessibilityElementInfo object. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_AccessibilityEventSetElementInfo( + ArkUI_AccessibilityEventInfo* eventInfo, ArkUI_AccessibilityElementInfo* elementInfo); + +/** +* @brief Obtains the value of a key from an ArkUI_AccessibilityActionArguments object. +* +* @param arguments Indicates the pointer to an ArkUI_AccessibilityActionArguments object. +* @param key Indicates the key. +* @param value Indicates the value. +* @return Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL} if the operation is successful. +* Returns {@link ARKUI_ACCESSIBILITY_NATIVE_RESULT_BAD_PARAMETER} if a parameter is incorrect. +* @since 13 +*/ +int32_t OH_ArkUI_FindAccessibilityActionArgumentByKey( + ArkUI_AccessibilityActionArguments* arguments, const char* key, char** value); +#ifdef __cplusplus +}; +#endif +#endif // _NATIVE_INTERFACE_ACCESSIBILITY_H +/** @} */ \ No newline at end of file diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp index 2ade6dd389..081f999a43 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.cpp +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -379,15 +379,25 @@ void XComponentBase::SetNativeXComponent(OH_NativeXComponent* nativeXComponent){ if (OH_GetSdkApiVersion() >= 13) { LOGD("api version: %{public}d", OH_GetSdkApiVersion()); BindAccessibilityProviderCallback(); + + int32_t (*OH_NativeXComponent_GetNativeAccessibilityProvider)(OH_NativeXComponent*, ArkUI_AccessibilityProvider**) = + OhosAccessibilityDDL::DLLoadGetNativeA11yProvider("OH_NativeXComponent_GetNativeAccessibilityProvider"); + if (OH_NativeXComponent_GetNativeAccessibilityProvider == nullptr) { + LOGE("OH_NativeXComponent_GetNativeAccessibilityProvider is null, %{public}s", dlerror()); + } ArkUI_AccessibilityProvider* accessibilityProvider = nullptr; - int32_t ret1 = OH_NativeXComponent_GetNativeAccessibilityProvider( - nativeXComponent_, &accessibilityProvider); + int32_t ret1 = OH_NativeXComponent_GetNativeAccessibilityProvider(nativeXComponent_, &accessibilityProvider); if (ret1 != 0) { LOGE("OH_NativeXComponent_GetNativeAccessibilityProvider is failed"); return; } - int32_t ret2 = OH_ArkUI_AccessibilityProviderRegisterCallback( - accessibilityProvider, &accessibilityProviderCallback_); + + int32_t (*OH_ArkUI_AccessibilityProviderRegisterCallback)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityProviderCallbacks*) = + OhosAccessibilityDDL::DLLoadRegisterFunc("OH_ArkUI_AccessibilityProviderRegisterCallback"); + if (OH_ArkUI_AccessibilityProviderRegisterCallback == nullptr) { + LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is null, %{public}s", dlerror()); + } + int32_t ret2 = OH_ArkUI_AccessibilityProviderRegisterCallback(accessibilityProvider, &accessibilityProviderCallback_); if (ret2 != 0) { LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is failed"); return; diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.h b/shell/platform/ohos/ohos_xcomponent_adapter.h index 61a181395a..d2c1414613 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.h +++ b/shell/platform/ohos/ohos_xcomponent_adapter.h @@ -19,11 +19,11 @@ #include #include #include +#include #include "flutter/shell/platform/ohos/ohos_touch_processor.h" #include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" #include "napi/native_api.h" #include "napi_common.h" -#include #include "flutter/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h" namespace flutter { diff --git a/shell/platform/ohos/utils/ddl_utils.h b/shell/platform/ohos/utils/ddl_utils.h new file mode 100644 index 0000000000..5ddbb0e954 --- /dev/null +++ b/shell/platform/ohos/utils/ddl_utils.h @@ -0,0 +1,25 @@ +/* + * 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 DDL_UTILS_H +#define DDL_UTILS_H + +#include +using LIBHANDLE = void*; +#define LOAD_LIB(libPath) dlopen(libPath, RTLD_LAZY|RTLD_LOCAL) +#define CLOSE_LIB(libHandle) dlclose(libHandle) +#define LOAD_SYM(libHandle, symbol) dlsym(libHandle, symbol) + +#endif // FOUNDATION_ACE_INTERFACE_INNERKITS_ACE_UTILS_H -- Gitee From f19a53b336b01881660bc6b03d7a1565d3ead39c Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 29 Nov 2024 19:31:48 +0800 Subject: [PATCH 136/151] =?UTF-8?q?refactor:=E4=BC=98=E5=8C=96=E9=83=A8?= =?UTF-8?q?=E5=88=86=E9=9D=99=E6=80=81=E6=A3=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 248 +++++++++--------- .../platform/ohos/ohos_xcomponent_adapter.cpp | 56 ++-- 2 files changed, 147 insertions(+), 157 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 2e9522d681..2f7e259a7b 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -118,10 +118,10 @@ void OhosAccessibilityBridge::updateSemantics( // 获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 int32_t childNodeCount = node.childrenInTraversalOrder.size(); for (int32_t i = 0; i < childNodeCount; i++) { - g_parentChildIdVec.emplace_back( - std::make_pair(node.id, node.childrenInTraversalOrder[i])); - FML_DLOG(INFO) << "UpdateSemantics parentChildIdMap -> (" << node.id - << ", " << node.childrenInTraversalOrder[i] << ")"; + g_parentChildIdVec.emplace_back( + std::make_pair(node.id, node.childrenInTraversalOrder[i])); + FML_DLOG(INFO) << "UpdateSemantics parentChildIdMap -> (" << node.id + << ", " << node.childrenInTraversalOrder[i] << ")"; } // 当滑动节点产生滑动,并执行滑动处理 @@ -148,15 +148,13 @@ void OhosAccessibilityBridge::updateSemantics( _elementInfo = nullptr; } } - - // 判断是否触发liveRegion活动区,当前节点是否活跃 - if (node.HasFlag(FLAGS_::kIsLiveRegion)) { - FML_DLOG(INFO) - << "UpdateSemantics -> LiveRegion, node.id=" << node.id; - FlutterPageUpdate(ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); - } - } + // 判断是否触发liveRegion活动区,当前节点是否活跃 + if (node.HasFlag(FLAGS_::kIsLiveRegion)) { + FML_DLOG(INFO) << "UpdateSemantics -> LiveRegion, node.id=" << node.id; + FlutterPageUpdate(ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); + } + } // 遍历更新的actions,并将所有的actions的id添加进actionMap for (const auto& item : actions) { @@ -189,89 +187,88 @@ void OhosAccessibilityBridge::FlutterScrollExecution( flutter::SemanticsNode node, ArkUI_AccessibilityElementInfo* elementInfoFromList) { - double nodePosition = node.scrollPosition; - double nodeScrollExtentMax = node.scrollExtentMax; - double nodeScrollExtentMin = node.scrollExtentMin; - double infinity = std::numeric_limits::infinity(); - - // 设置flutter可滑动的最大范围值 - if (nodeScrollExtentMax == infinity) { - nodeScrollExtentMax = SCROLL_EXTENT_FOR_INFINITY; - if (nodePosition > SCROLL_POSITION_CAP_FOR_INFINITY) { - nodePosition = SCROLL_POSITION_CAP_FOR_INFINITY; - } - } - if (nodeScrollExtentMin == infinity) { - nodeScrollExtentMax += SCROLL_EXTENT_FOR_INFINITY; - if (nodePosition < -SCROLL_POSITION_CAP_FOR_INFINITY) { - nodePosition = -SCROLL_POSITION_CAP_FOR_INFINITY; - } - nodePosition += SCROLL_EXTENT_FOR_INFINITY; - } else { - nodeScrollExtentMax -= node.scrollExtentMin; - nodePosition -= node.scrollExtentMin; - } - - if (node.HasAction(ACTIONS_::kScrollUp) || - node.HasAction(ACTIONS_::kScrollDown)) { - } else if (node.HasAction(ACTIONS_::kScrollLeft) || - node.HasAction(ACTIONS_::kScrollRight)) { - } - - // 当可滑动组件存在滑动子节点 - if (node.scrollChildren > 0) { - // 配置当前滑动组件的子节点总数 - int32_t itemCount = node.scrollChildren; - if (OH_GetSdkApiVersion() >= 13) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetItemCount)(ArkUI_AccessibilityElementInfo*, int32_t) = - OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetItemCount"); - if (OH_ArkUI_AccessibilityElementInfoSetItemCount == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetItemCount is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetItemCount(elementInfoFromList, itemCount)); - - // 设置当前页面可见的起始滑动index - int32_t startItemIndex = node.scrollIndex; - int32_t (*OH_ArkUI_AccessibilityElementInfoSetStartItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = - OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetStartItemIndex"); - if (OH_ArkUI_AccessibilityElementInfoSetStartItemIndex == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetStartItemIndex is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, startItemIndex)); - - // 计算当前滑动位置页面的可见子滑动节点数量 - int visibleChildren = 0; - // handle hidden children at the beginning and end of the list. - for (const auto& childId : node.childrenInHitTestOrder) { - auto childNode = GetFlutterSemanticsNode(childId); - if (!childNode.HasFlag(FLAGS_::kIsHidden)) { - visibleChildren += 1; - } + double nodePosition = node.scrollPosition; + double nodeScrollExtentMax = node.scrollExtentMax; + double nodeScrollExtentMin = node.scrollExtentMin; + double infinity = std::numeric_limits::infinity(); + + // 设置flutter可滑动的最大范围值 + if (nodeScrollExtentMax == infinity) { + nodeScrollExtentMax = SCROLL_EXTENT_FOR_INFINITY; + if (nodePosition > SCROLL_POSITION_CAP_FOR_INFINITY) { + nodePosition = SCROLL_POSITION_CAP_FOR_INFINITY; + } } - // 当可见滑动子节点数量超过滑动组件总子节点数量 - if (node.scrollIndex + visibleChildren > node.scrollChildren) { - FML_DLOG(WARNING) - << "FlutterScrollExecution -> Scroll index is out of bounds"; + if (nodeScrollExtentMin == infinity) { + nodeScrollExtentMax += SCROLL_EXTENT_FOR_INFINITY; + if (nodePosition < -SCROLL_POSITION_CAP_FOR_INFINITY) { + nodePosition = -SCROLL_POSITION_CAP_FOR_INFINITY; + } + nodePosition += SCROLL_EXTENT_FOR_INFINITY; + } else { + nodeScrollExtentMax -= node.scrollExtentMin; + nodePosition -= node.scrollExtentMin; } - // 当滑动击中子节点数量为0 - if (!node.childrenInHitTestOrder.size()) { - FML_DLOG(WARNING) << "FlutterScrollExecution -> Had scrollChildren but no " - "childrenInHitTestOrder"; + + if (node.HasAction(ACTIONS_::kScrollUp) || + node.HasAction(ACTIONS_::kScrollDown)) { + } else if (node.HasAction(ACTIONS_::kScrollLeft) || + node.HasAction(ACTIONS_::kScrollRight)) { } - // 设置当前页面可见的末尾滑动index - int32_t endItemIndex = node.scrollIndex + visibleChildren - 1; - int32_t (*OH_ArkUI_AccessibilityElementInfoSetEndItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = - OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetEndItemIndex"); - if (OH_ArkUI_AccessibilityElementInfoSetEndItemIndex == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetEndItemIndex is null, %{public}s", dlerror()); + + // 当可滑动组件存在滑动子节点 + if (node.scrollChildren > 0) { + // 配置当前滑动组件的子节点总数 + int32_t itemCount = node.scrollChildren; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetItemCount)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetItemCount"); + if (OH_ArkUI_AccessibilityElementInfoSetItemCount == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetItemCount is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetItemCount(elementInfoFromList, itemCount)); + + // 设置当前页面可见的起始滑动index + int32_t startItemIndex = node.scrollIndex; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetStartItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetStartItemIndex"); + if (OH_ArkUI_AccessibilityElementInfoSetStartItemIndex == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetStartItemIndex is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, startItemIndex)); + + // 计算当前滑动位置页面的可见子滑动节点数量 + int visibleChildren = 0; + // handle hidden children at the beginning and end of the list. + for (const auto& childId : node.childrenInHitTestOrder) { + auto childNode = GetFlutterSemanticsNode(childId); + if (!childNode.HasFlag(FLAGS_::kIsHidden)) { + visibleChildren += 1; + } + } + // 当可见滑动子节点数量超过滑动组件总子节点数量 + if (node.scrollIndex + visibleChildren > node.scrollChildren) { + FML_DLOG(WARNING) + << "FlutterScrollExecution -> Scroll index is out of bounds"; + } + // 当滑动击中子节点数量为0 + if (!node.childrenInHitTestOrder.size()) { + FML_DLOG(WARNING) << "FlutterScrollExecution -> Had scrollChildren but no " + "childrenInHitTestOrder"; + } + // 设置当前页面可见的末尾滑动index + int32_t endItemIndex = node.scrollIndex + visibleChildren - 1; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEndItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetEndItemIndex"); + if (OH_ArkUI_AccessibilityElementInfoSetEndItemIndex == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetEndItemIndex is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetEndItemIndex(elementInfoFromList, endItemIndex) + ); } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetEndItemIndex(elementInfoFromList, endItemIndex) - ); } - - } + } /** @@ -494,15 +491,14 @@ flutter::SemanticsNode OhosAccessibilityBridge::GetFlutterRootSemanticsNode() flutter::SemanticsNode OhosAccessibilityBridge::GetFlutterSemanticsNode( int32_t id) { - flutter::SemanticsNode node; - if (g_flutterSemanticsTree.count(id) > 0) { - return g_flutterSemanticsTree.at(id); - FML_DLOG(INFO) << "GetFlutterSemanticsNode get node.id=" << id; - } else { - FML_DLOG(ERROR) - << "GetFlutterSemanticsNode g_flutterSemanticsTree = null" << id; - return {}; - } + flutter::SemanticsNode node; + if (g_flutterSemanticsTree.count(id) > 0) { + return g_flutterSemanticsTree.at(id); + FML_DLOG(INFO) << "GetFlutterSemanticsNode get node.id=" << id; + } else { + FML_DLOG(ERROR) << "GetFlutterSemanticsNode g_flutterSemanticsTree = null" << id; + return {}; + } } /** @@ -599,7 +595,7 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfo, childCount, childNodeIds) ); - // 配置常用属性,force to true for debugging + // 配置常用属性 int32_t (*OH_ArkUI_AccessibilityElementInfoSetCheckable)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetCheckable"); if (OH_ArkUI_AccessibilityElementInfoSetCheckable == nullptr) { @@ -784,8 +780,8 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( if (_kMScaleX > 1 && _kMScaleY > 1) { // 子节点相对父节点进行变化(缩放、 平移) newLeft = currLeft + _kMTransX * _kMScaleX; - newTop = currTop + _kMTransY * _kMScaleY; - newRight = currRight * _kMScaleX; + newTop = currTop + _kMTransY * _kMScaleY; + newRight = currRight * _kMScaleX; newBottom = currBottom * _kMScaleY; // 更新当前flutter节点currNode的相对坐标 -> 屏幕绝对坐标 SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); @@ -800,10 +796,8 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( // 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 newLeft = (currLeft + _kMTransX) * realScaleFactor + realParentLeft; newTop = (currTop + _kMTransY) * realScaleFactor + realParentTop; - newRight = - (currLeft + _kMTransX + currRight) * realScaleFactor + realParentLeft; - newBottom = - (currTop + _kMTransY + currBottom) * realScaleFactor + realParentTop; + newRight = (currLeft + _kMTransX + currRight) * realScaleFactor + realParentLeft; + newBottom = (currTop + _kMTransY + currBottom) * realScaleFactor + realParentTop; } // 若子节点rect超过父节点则跳过显示(单个屏幕显示不下,滑动再重新显示) const bool IS_OVER_SCREEN_AREA = newLeft < realParentLeft || @@ -850,8 +844,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( // 当elementId = -1或0时,创建root节点 if (elementId == 0 || elementId == -1) { // 获取flutter的root节点 - flutter::SemanticsNode flutterNode = - GetFlutterSemanticsNode(static_cast(0)); + flutter::SemanticsNode flutterNode = GetFlutterSemanticsNode(static_cast(0)); // 设置elementinfo的屏幕坐标范围 int32_t left = static_cast(flutterNode.rect.fLeft); @@ -943,6 +936,12 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( ); // 配置root节点常用属性 + int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); + if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true)); int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetFocusable"); if (OH_ArkUI_AccessibilityElementInfoSetFocusable == nullptr) { @@ -964,13 +963,6 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( } ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true)); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); - if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true)); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetComponentType"); if (OH_ArkUI_AccessibilityElementInfoSetComponentType == nullptr) { @@ -998,7 +990,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( bool OhosAccessibilityBridge::Contains(const std::string source, const std::string target) { - return source.find(target) != std::string::npos; + return source.find(target) != std::string::npos; } /** @@ -1525,13 +1517,12 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( FML_DLOG(INFO) << "FindAccessibilityNodeInfosById elementList is null"; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } + // 开启无障碍导航功能 + if(elementId == -1 || elementId == 0) { + accessibilityFeatures_->SetAccessibleNavigation(true, native_shell_holder_id_); + } if (OH_GetSdkApiVersion() >= 13) { - // 开启无障碍导航功能 - if(elementId == -1 || elementId == 0) { - accessibilityFeatures_->SetAccessibleNavigation(true, native_shell_holder_id_); - } - // 从elementinfolist中获取elementinfo ArkUI_AccessibilityElementInfo* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); @@ -1541,18 +1532,17 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( ArkUI_AccessibilityElementInfo* elementInfoFromList = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); if (elementInfoFromList == nullptr) { - FML_DLOG(INFO) - << "FindAccessibilityNodeInfosById elementInfoFromList is null"; + FML_DLOG(INFO) << "FindAccessibilityNodeInfosById elementInfoFromList is null"; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } // 过滤非当前屏幕显示的语义节点创建、配置,防止溢出屏幕坐标绘制bug以及优化性能开销 auto flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); - bool VISIBLE_STATE = elementId == -1; - if (!VISIBLE_STATE && !IsNodeVisible(flutterNode)) { - FML_DLOG(INFO) << "filter hidden nodes, elementId:" << elementId; - return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; - } + // bool VISIBLE_STATE = elementId == -1; + // if (!VISIBLE_STATE && !IsNodeVisible(flutterNode)) { + // FML_DLOG(INFO) << "filter hidden nodes, elementId:" << elementId; + // return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; + // } if (mode == ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { /** Search for current nodes. (mode = 0) */ @@ -2140,7 +2130,7 @@ bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) bool OhosAccessibilityBridge::IsNodeClickable( flutter::SemanticsNode flutterNode) { - return flutterNode.HasAction(ACTIONS_::kTap) || + return flutterNode.HasAction(ACTIONS_::kTap); flutterNode.HasFlag(FLAGS_::kHasCheckedState) || flutterNode.HasFlag(FLAGS_::kIsButton) || flutterNode.HasFlag(FLAGS_::kIsTextField) || diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp index 081f999a43..e9a0e82d03 100644 --- a/shell/platform/ohos/ohos_xcomponent_adapter.cpp +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -377,38 +377,38 @@ void XComponentBase::SetNativeXComponent(OH_NativeXComponent* nativeXComponent){ OH_NativeXComponent_RegisterMouseEventCallback(nativeXComponent_, &mouseCallback_); if (OH_GetSdkApiVersion() >= 13) { - LOGD("api version: %{public}d", OH_GetSdkApiVersion()); - BindAccessibilityProviderCallback(); + LOGD("api version: %{public}d", OH_GetSdkApiVersion()); + BindAccessibilityProviderCallback(); - int32_t (*OH_NativeXComponent_GetNativeAccessibilityProvider)(OH_NativeXComponent*, ArkUI_AccessibilityProvider**) = - OhosAccessibilityDDL::DLLoadGetNativeA11yProvider("OH_NativeXComponent_GetNativeAccessibilityProvider"); - if (OH_NativeXComponent_GetNativeAccessibilityProvider == nullptr) { - LOGE("OH_NativeXComponent_GetNativeAccessibilityProvider is null, %{public}s", dlerror()); - } - ArkUI_AccessibilityProvider* accessibilityProvider = nullptr; - int32_t ret1 = OH_NativeXComponent_GetNativeAccessibilityProvider(nativeXComponent_, &accessibilityProvider); - if (ret1 != 0) { - LOGE("OH_NativeXComponent_GetNativeAccessibilityProvider is failed"); - return; - } + int32_t (*OH_NativeXComponent_GetNativeAccessibilityProvider)(OH_NativeXComponent*, ArkUI_AccessibilityProvider**) = + OhosAccessibilityDDL::DLLoadGetNativeA11yProvider("OH_NativeXComponent_GetNativeAccessibilityProvider"); + if (OH_NativeXComponent_GetNativeAccessibilityProvider == nullptr) { + LOGE("OH_NativeXComponent_GetNativeAccessibilityProvider is null, %{public}s", dlerror()); + } + ArkUI_AccessibilityProvider* accessibilityProvider = nullptr; + int32_t ret1 = OH_NativeXComponent_GetNativeAccessibilityProvider(nativeXComponent_, &accessibilityProvider); + if (ret1 != 0) { + LOGE("OH_NativeXComponent_GetNativeAccessibilityProvider is failed"); + return; + } - int32_t (*OH_ArkUI_AccessibilityProviderRegisterCallback)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityProviderCallbacks*) = - OhosAccessibilityDDL::DLLoadRegisterFunc("OH_ArkUI_AccessibilityProviderRegisterCallback"); - if (OH_ArkUI_AccessibilityProviderRegisterCallback == nullptr) { - LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is null, %{public}s", dlerror()); - } - int32_t ret2 = OH_ArkUI_AccessibilityProviderRegisterCallback(accessibilityProvider, &accessibilityProviderCallback_); - if (ret2 != 0) { - LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is failed"); - return; - } - LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is %{public}d", ret2); + int32_t (*OH_ArkUI_AccessibilityProviderRegisterCallback)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityProviderCallbacks*) = + OhosAccessibilityDDL::DLLoadRegisterFunc("OH_ArkUI_AccessibilityProviderRegisterCallback"); + if (OH_ArkUI_AccessibilityProviderRegisterCallback == nullptr) { + LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is null, %{public}s", dlerror()); + } + int32_t ret2 = OH_ArkUI_AccessibilityProviderRegisterCallback(accessibilityProvider, &accessibilityProviderCallback_); + if (ret2 != 0) { + LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is failed"); + return; + } + LOGE("OH_ArkUI_AccessibilityProviderRegisterCallback is %{public}d", ret2); - //将ArkUI_AccessibilityProvider传到无障碍bridge类 - auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); - ohosAccessibilityBridge->provider_ = accessibilityProvider; + //将ArkUI_AccessibilityProvider传到无障碍bridge类 + auto ohosAccessibilityBridge = OhosAccessibilityBridge::GetInstance(); + ohosAccessibilityBridge->provider_ = accessibilityProvider; - LOGI("XComponentBase::SetNativeXComponent OH_ArkUI_AccessibilityProviderRegisterCallback is succeed"); + LOGI("XComponentBase::SetNativeXComponent OH_ArkUI_AccessibilityProviderRegisterCallback is succeed"); } } } -- Gitee From 0989c5d82256fc57adb13b39e4f961bebca05377 Mon Sep 17 00:00:00 2001 From: zjxi Date: Sat, 30 Nov 2024 10:28:29 +0800 Subject: [PATCH 137/151] fix: Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 79 +++++++++---------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 2f7e259a7b..ce70e4e516 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -125,7 +125,7 @@ void OhosAccessibilityBridge::updateSemantics( } // 当滑动节点产生滑动,并执行滑动处理 - if (HasScrolled(node) && IsNodeVisible(node)) { + if (HasScrolled(node)) { LOGD("UpdateSemantics -> has scrolled"); if (OH_GetSdkApiVersion() >= 13) { ArkUI_AccessibilityElementInfo* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = @@ -133,8 +133,7 @@ void OhosAccessibilityBridge::updateSemantics( if (OH_ArkUI_CreateAccessibilityElementInfo == nullptr) { LOGE("OH_ArkUI_CreateAccessibilityElementInfo is null, %{public}s", dlerror()); } - ArkUI_AccessibilityElementInfo* _elementInfo = - OH_ArkUI_CreateAccessibilityElementInfo(); + ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); FlutterNodeToElementInfoById(_elementInfo, static_cast(node.id)); FlutterScrollExecution(node, _elementInfo); @@ -268,7 +267,6 @@ void OhosAccessibilityBridge::FlutterScrollExecution( ); } } - } /** @@ -596,6 +594,19 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( ); // 配置常用属性 + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); + if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfo, true)); + + int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); + if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfo, true)); int32_t (*OH_ArkUI_AccessibilityElementInfoSetCheckable)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetCheckable"); if (OH_ArkUI_AccessibilityElementInfoSetCheckable == nullptr) { @@ -616,20 +627,6 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( LOGE("OH_ArkUI_AccessibilityElementInfoSetVisible is null, %{public}s", dlerror()); } ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfo, true)); - - int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); - if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfo, true)); - - int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); - if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfo, true)); // 设置组件类型 std::string componentTypeName = GetNodeComponentType(flutterNode); @@ -813,9 +810,8 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( << ", " << newRight << ", " << newBottom << ")}"; // 防止滑动场景下绿框坐标超出屏幕范围,进行正则化处理 // newLeft = static_cast(newLeft) % static_cast(rootWidth); - newTop = static_cast(newTop) % static_cast(rootHeight); - // newRight = static_cast(newRight) % static_cast(rootWidth); - newBottom = static_cast(newBottom) % static_cast(rootHeight); + newTop -= rootHeight; + newBottom -= rootHeight; SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); } else { SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); @@ -936,12 +932,20 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( ); // 配置root节点常用属性 + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); + if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true)); + int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); } ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true)); + int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetFocusable"); if (OH_ArkUI_AccessibilityElementInfoSetFocusable == nullptr) { @@ -956,13 +960,6 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( } ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true)); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); - if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true)); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetComponentType"); if (OH_ArkUI_AccessibilityElementInfoSetComponentType == nullptr) { @@ -1230,6 +1227,19 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( /** * 根据当前flutter节点的SemanticsFlags特性,配置对应的elmentinfo属性 */ + // 判断当前节点组件是否enabled + if (IsNodeEnabled(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); + if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetEnabled -> true"; + } // 判断当前节点是否可点击 if (IsNodeClickable(flutterNode)) { int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = @@ -1364,19 +1374,6 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( << "flutterNode.id=" << flutterNode.id << " OH_ArkUI_AccessibilityElementInfoSetLongClickable -> true"; } - // 判断当前节点组件是否enabled - if (IsNodeEnabled(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); - if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetEnabled -> true"; - } // 获取当前节点的组件类型 std::string componentTypeName = GetNodeComponentType(flutterNode); -- Gitee From c05f7b894a90aa6ae43031a6f594dfac421f7168 Mon Sep 17 00:00:00 2001 From: zjxi Date: Sat, 30 Nov 2024 10:35:07 +0800 Subject: [PATCH 138/151] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E4=B8=80?= =?UTF-8?q?=E4=BA=9Bbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../platform/ohos/accessibility/ohos_accessibility_bridge.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index ce70e4e516..4a27a33724 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -115,6 +115,10 @@ void OhosAccessibilityBridge::updateSemantics( */ g_flutterSemanticsTree[node.id] = node; + if(!IsNodeVisible(node)) { + continue; + } + // 获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 int32_t childNodeCount = node.childrenInTraversalOrder.size(); for (int32_t i = 0; i < childNodeCount; i++) { -- Gitee From c88ea38e3da3f8d5cb19afc38fad060422fcddef Mon Sep 17 00:00:00 2001 From: zjxi Date: Sat, 30 Nov 2024 11:24:45 +0800 Subject: [PATCH 139/151] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E9=9D=99=E6=80=81=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 655 +++++++++--------- 1 file changed, 324 insertions(+), 331 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 4a27a33724..5bda8bfaea 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -280,42 +280,42 @@ void OhosAccessibilityBridge::FlutterPageUpdate( ArkUI_AccessibilityEventType eventType) { if (provider_ == nullptr) { - FML_DLOG(ERROR) << "PageStateUpdate ->" - "AccessibilityProvider = nullptr"; - return; + FML_DLOG(ERROR) << "PageStateUpdate ->" + "AccessibilityProvider = nullptr"; + return; } if (OH_GetSdkApiVersion() >= 13) { ArkUI_AccessibilityEventInfo* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); if (OH_ArkUI_CreateAccessibilityEventInfo == nullptr) { - LOGE("OH_ArkUI_CreateAccessibilityEventInfo is null, %{public}s", dlerror()); + LOGE("OH_ArkUI_CreateAccessibilityEventInfo is null, %{public}s", dlerror()); } ArkUI_AccessibilityEventInfo* pageUpdateEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = OhosAccessibilityDDL::DLLoadSetEventFunc("OH_ArkUI_AccessibilityEventSetEventType"); if (OH_ArkUI_AccessibilityEventSetEventType == nullptr) { - LOGE("OH_ArkUI_AccessibilityEventSetEventType is null, %{public}s", dlerror()); + LOGE("OH_ArkUI_AccessibilityEventSetEventType is null, %{public}s", dlerror()); } ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityEventSetEventType(pageUpdateEventInfo, eventType) ); auto callback = [](int32_t errorCode) { - FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; + FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; }; void (*OH_ArkUI_SendAccessibilityAsyncEvent)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*callback)(int32_t)) = OhosAccessibilityDDL::DLLoadSendAsyncEventFunc("OH_ArkUI_SendAccessibilityAsyncEvent"); if (OH_ArkUI_SendAccessibilityAsyncEvent == nullptr) { - LOGE("OH_ArkUI_SendAccessibilityAsyncEvent is null, %{public}s", dlerror()); + LOGE("OH_ArkUI_SendAccessibilityAsyncEvent is null, %{public}s", dlerror()); } OH_ArkUI_SendAccessibilityAsyncEvent(provider_, pageUpdateEventInfo, callback); void (*OH_ArkUI_DestoryAccessibilityEventInfo)(ArkUI_AccessibilityEventInfo*) = OhosAccessibilityDDL::DLLoadDestroyEventFunc("OH_ArkUI_DestoryAccessibilityEventInfo"); if (OH_ArkUI_DestoryAccessibilityEventInfo == nullptr) { - LOGE("OH_ArkUI_DestoryAccessibilityEventInfo is null, %{public}s", dlerror()); + LOGE("OH_ArkUI_DestoryAccessibilityEventInfo is null, %{public}s", dlerror()); } OH_ArkUI_DestoryAccessibilityEventInfo(pageUpdateEventInfo); pageUpdateEventInfo = nullptr; @@ -336,7 +336,7 @@ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() ArkUI_AccessibilityEventInfo* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); if (OH_ArkUI_CreateAccessibilityEventInfo == nullptr) { - LOGE("OH_ArkUI_CreateAccessibilityEventInfo is null, %{public}s", dlerror()); + LOGE("OH_ArkUI_CreateAccessibilityEventInfo is null, %{public}s", dlerror()); } ArkUI_AccessibilityEventInfo* reqFocusEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); @@ -350,7 +350,7 @@ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = OhosAccessibilityDDL::DLLoadSetEventFunc("OH_ArkUI_AccessibilityEventSetEventType"); if (OH_ArkUI_AccessibilityEventSetEventType == nullptr) { - LOGE("OH_ArkUI_AccessibilityEventSetEventType is null, %{public}s", dlerror()); + LOGE("OH_ArkUI_AccessibilityEventSetEventType is null, %{public}s", dlerror()); } ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityEventSetEventType( @@ -363,7 +363,7 @@ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() int32_t (*OH_ArkUI_AccessibilityEventSetRequestFocusId)(ArkUI_AccessibilityEventInfo*, int32_t) = OhosAccessibilityDDL::DLLoadSetReqFocusFunc("OH_ArkUI_AccessibilityEventSetRequestFocusId"); if (OH_ArkUI_AccessibilityEventSetRequestFocusId == nullptr) { - LOGE("OH_ArkUI_AccessibilityEventSetRequestFocusId is null, %{public}s", dlerror()); + LOGE("OH_ArkUI_AccessibilityEventSetRequestFocusId is null, %{public}s", dlerror()); } ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityEventSetRequestFocusId(reqFocusEventInfo, @@ -570,11 +570,11 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( LOGE("OH_ArkUI_AccessibilityElementInfoSetParentId is null, %{public}s", dlerror()); } if (flutterNode.id == 0) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, ARKUI_ACCESSIBILITY_ROOT_PARENT_ID) - ); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, ARKUI_ACCESSIBILITY_ROOT_PARENT_ID) + ); } else { - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, parentId)); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, parentId)); } // 设置孩子节点 @@ -768,7 +768,6 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( // 获取root节点的绝对坐标, 即xcomponent屏幕长宽 auto _rootRect = GetAbsoluteScreenRect(0); - // float rootWidth = _rootRect.second.first; auto rootHeight = _rootRect.second.second; // 真实缩放系数 @@ -813,7 +812,6 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( << currNode.id << ", (" << newLeft << ", " << newTop << ", " << newRight << ", " << newBottom << ")}"; // 防止滑动场景下绿框坐标超出屏幕范围,进行正则化处理 - // newLeft = static_cast(newLeft) % static_cast(rootWidth); newTop -= rootHeight; newBottom -= rootHeight; SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); @@ -1150,17 +1148,17 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( // 配置arkui的elementinfo可操作动作属性 if (IsTextField(flutterNode)) { - // 若当前flutter节点为文本输入框组件 - std::string widget_type = "textfield"; - FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); + // 若当前flutter节点为文本输入框组件 + std::string widget_type = "textfield"; + FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); } else if (IsScrollableWidget(flutterNode) || IsNodeScrollable(flutterNode)) { - // 若当前flutter节点为可滑动组件类型 - std::string widget_type = "scrollable"; - FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); + // 若当前flutter节点为可滑动组件类型 + std::string widget_type = "scrollable"; + FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); } else { - // 若当前flutter节点为通用组件 - std::string widget_type = "common"; - FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); + // 若当前flutter节点为通用组件 + std::string widget_type = "common"; + FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); } // set current elementinfo parent id @@ -1214,10 +1212,10 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); int64_t childNodeIds[childCount]; for (int32_t i = 0; i < childCount; i++) { - childNodeIds[i] = static_cast(childrenIdsVec[i]); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> elementid=" << elementId - << " childCount=" << childCount - << " childNodeIds=" << childNodeIds[i]; + childNodeIds[i] = static_cast(childrenIdsVec[i]); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> elementid=" << elementId + << " childCount=" << childCount + << " childNodeIds=" << childNodeIds[i]; } int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); @@ -1233,136 +1231,136 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( */ // 判断当前节点组件是否enabled if (IsNodeEnabled(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); - if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetEnabled -> true"; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); + if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetEnabled -> true"; } // 判断当前节点是否可点击 if (IsNodeClickable(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); - if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetClickable -> true"; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); + if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetClickable -> true"; } // 判断当前节点是否可获焦点 if (IsNodeFocusable(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetFocusable"); - if (OH_ArkUI_AccessibilityElementInfoSetFocusable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetFocusable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetFocusable -> true"; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetFocusable"); + if (OH_ArkUI_AccessibilityElementInfoSetFocusable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetFocusable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetFocusable -> true"; } // 判断当前节点是否为密码输入框 if (IsNodePassword(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetIsPassword)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetIsPassword"); - if (OH_ArkUI_AccessibilityElementInfoSetIsPassword == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetIsPassword is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetIsPassword(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetIsPassword -> true"; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetIsPassword)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetIsPassword"); + if (OH_ArkUI_AccessibilityElementInfoSetIsPassword == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetIsPassword is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetIsPassword(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetIsPassword -> true"; } // 判断当前节点是否具备checkable状态 (如:checkbox, radio button) if (IsNodeCheckable(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetCheckable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetCheckable"); - if (OH_ArkUI_AccessibilityElementInfoSetCheckable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetCheckable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetCheckable -> true"; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetCheckable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetCheckable"); + if (OH_ArkUI_AccessibilityElementInfoSetCheckable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetCheckable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetCheckable -> true"; } // 判断当前节点(check box/radio button)是否checked/unchecked if (IsNodeChecked(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetChecked)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetChecked"); - if (OH_ArkUI_AccessibilityElementInfoSetChecked == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetChecked is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetChecked(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetChecked -> true"; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetChecked)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetChecked"); + if (OH_ArkUI_AccessibilityElementInfoSetChecked == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetChecked is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetChecked(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetChecked -> true"; } // 判断当前节点组件是否可显示 if (IsNodeVisible(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetVisible)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetVisible"); - if (OH_ArkUI_AccessibilityElementInfoSetVisible == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetVisible is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetVisible -> true"; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetVisible)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetVisible"); + if (OH_ArkUI_AccessibilityElementInfoSetVisible == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetVisible is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetVisible -> true"; } // 判断当前节点组件是否选中 if (IsNodeSelected(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetSelected)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetSelected"); - if (OH_ArkUI_AccessibilityElementInfoSetSelected == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetSelected is null, %{public}s", dlerror()); - } - OH_ArkUI_AccessibilityElementInfoSetSelected(elementInfoFromList, true); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetSelected -> true"; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetSelected)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetSelected"); + if (OH_ArkUI_AccessibilityElementInfoSetSelected == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetSelected is null, %{public}s", dlerror()); + } + OH_ArkUI_AccessibilityElementInfoSetSelected(elementInfoFromList, true); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetSelected -> true"; } // 判断当前节点组件是否可滑动 if (IsNodeScrollable(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetScrollable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetScrollable"); - if (OH_ArkUI_AccessibilityElementInfoSetScrollable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetScrollable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetScrollable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetScrollable -> true"; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetScrollable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetScrollable"); + if (OH_ArkUI_AccessibilityElementInfoSetScrollable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetScrollable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetScrollable(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetScrollable -> true"; } // 判断当前节点组件是否可编辑(文本输入框) if (IsTextField(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetEditable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEditable"); - if (OH_ArkUI_AccessibilityElementInfoSetEditable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetEditable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetEditable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetEditable -> true"; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEditable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEditable"); + if (OH_ArkUI_AccessibilityElementInfoSetEditable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetEditable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetEditable(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetEditable -> true"; } // 判断当前节点组件是否为滑动条 if (IsSlider(flutterNode)) { - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetRangeInfo -> true"; + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetRangeInfo -> true"; } // 判断当前节点组件是否支持长按 if (IsNodeHasLongPress(flutterNode)) { @@ -1390,14 +1388,14 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( LOGE("OH_ArkUI_AccessibilityElementInfoSetComponentType is null, %{public}s", dlerror()); } if (elementId == 0) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root") - ); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root") + ); } else { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, - componentTypeName.c_str()) - ); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, + componentTypeName.c_str()) + ); } FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetComponentType: " << componentTypeName; @@ -1539,11 +1537,6 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( // 过滤非当前屏幕显示的语义节点创建、配置,防止溢出屏幕坐标绘制bug以及优化性能开销 auto flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); - // bool VISIBLE_STATE = elementId == -1; - // if (!VISIBLE_STATE && !IsNodeVisible(flutterNode)) { - // FML_DLOG(INFO) << "filter hidden nodes, elementId:" << elementId; - // return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; - // } if (mode == ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { /** Search for current nodes. (mode = 0) */ @@ -1615,200 +1608,200 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( switch (action) { /** Response to a click. 16 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: { - /** Click event, sent after the UI component responds. 1 */ - auto clickEventType = ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_CLICKED; - Flutter_SendAccessibilityAsyncEvent(elementId, clickEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: click(" << action - << ")" << " event: click(" << clickEventType << ")"; - // 解析arkui的屏幕点击 -> flutter对应节点的屏幕点击 - auto flutterTapAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), flutterTapAction, - {}); - break; - } - /** Response to a long click. 32 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: { - /** Long click event, sent after the UI component responds. 2 */ - auto longClickEventType = ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_LONG_CLICKED; - Flutter_SendAccessibilityAsyncEvent(elementId, longClickEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: longclick(" - << action << ")" << " event: longclick(" - << longClickEventType << ")"; - // 解析arkui的屏幕动作 -> flutter对应节点的屏幕动作 - auto flutterLongPressAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), - flutterLongPressAction, {}); - break; - } - /** Accessibility focus acquisition. 64 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: { - // 解析arkui的获焦 -> flutter对应节点的获焦 - auto flutterGainFocusAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), - flutterGainFocusAction, {}); - // Accessibility focus event, sent after the UI component responds. 32768 - auto focusEventType = ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; - Flutter_SendAccessibilityAsyncEvent(elementId, focusEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: focus(" << action - << ")" << " event: focus(" << focusEventType << ")"; - if (flutterNode.HasAction(ACTIONS_::kIncrease) || - flutterNode.HasAction(ACTIONS_::kDecrease)) { - Flutter_SendAccessibilityAsyncEvent( - elementId, ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); - } - break; - } - /** Accessibility focus clearance. 128 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: { - // 解析arkui的失焦 -> flutter对应节点的失焦 - auto flutterLoseFocusAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), - flutterLoseFocusAction, {}); - /** Accessibility focus cleared event, sent after the UI component - * responds. 65536 */ - auto clearFocusEventType = ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED; - Flutter_SendAccessibilityAsyncEvent(elementId, clearFocusEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: clearfocus(" - << action << ")" << " event: clearfocus(" - << clearFocusEventType << ")"; - break; - } - /** Forward scroll action. 256 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: { - // flutter scroll forward with different situations - if (flutterNode.HasAction(ACTIONS_::kScrollUp)) { - auto flutterScrollUpAction = ArkuiActionsToFlutterActions(action); + /** Click event, sent after the UI component responds. 1 */ + auto clickEventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_CLICKED; + Flutter_SendAccessibilityAsyncEvent(elementId, clickEventType); + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: click(" << action + << ")" << " event: click(" << clickEventType << ")"; + // 解析arkui的屏幕点击 -> flutter对应节点的屏幕点击 + auto flutterTapAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), flutterTapAction, + {}); + break; + } + /** Response to a long click. 32 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: { + /** Long click event, sent after the UI component responds. 2 */ + auto longClickEventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_LONG_CLICKED; + Flutter_SendAccessibilityAsyncEvent(elementId, longClickEventType); + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: longclick(" + << action << ")" << " event: longclick(" + << longClickEventType << ")"; + // 解析arkui的屏幕动作 -> flutter对应节点的屏幕动作 + auto flutterLongPressAction = ArkuiActionsToFlutterActions(action); DispatchSemanticsAction(static_cast(elementId), - flutterScrollUpAction, {}); - } else if (flutterNode.HasAction(ACTIONS_::kScrollLeft)) { + flutterLongPressAction, {}); + break; + } + /** Accessibility focus acquisition. 64 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: { + // 解析arkui的获焦 -> flutter对应节点的获焦 + auto flutterGainFocusAction = ArkuiActionsToFlutterActions(action); DispatchSemanticsAction(static_cast(elementId), - ACTIONS_::kScrollLeft, {}); - } else if (flutterNode.HasAction(ACTIONS_::kIncrease)) { - flutterNode.value = flutterNode.increasedValue; - flutterNode.valueAttributes = flutterNode.increasedValueAttributes; - - Flutter_SendAccessibilityAsyncEvent( - elementId, ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + flutterGainFocusAction, {}); + // Accessibility focus event, sent after the UI component responds. 32768 + auto focusEventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; + Flutter_SendAccessibilityAsyncEvent(elementId, focusEventType); + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: focus(" << action + << ")" << " event: focus(" << focusEventType << ")"; + if (flutterNode.HasAction(ACTIONS_::kIncrease) || + flutterNode.HasAction(ACTIONS_::kDecrease)) { + Flutter_SendAccessibilityAsyncEvent( + elementId, ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + } + break; + } + /** Accessibility focus clearance. 128 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: { + // 解析arkui的失焦 -> flutter对应节点的失焦 + auto flutterLoseFocusAction = ArkuiActionsToFlutterActions(action); DispatchSemanticsAction(static_cast(elementId), - ACTIONS_::kIncrease, {}); - } else { - } - std::string currComponetType = GetNodeComponentType(flutterNode); - if (currComponetType == "ListView") { - /** Scrolled event, sent when a scrollable component experiences a - * scroll event. 4096 */ - ArkUI_AccessibilityEventType scrollEventType1 = - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; - Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); + flutterLoseFocusAction, {}); + /** Accessibility focus cleared event, sent after the UI component + * responds. 65536 */ + auto clearFocusEventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED; + Flutter_SendAccessibilityAsyncEvent(elementId, clearFocusEventType); + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: clearfocus(" + << action << ")" << " event: clearfocus(" + << clearFocusEventType << ")"; + break; + } + /** Forward scroll action. 256 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: { + // flutter scroll forward with different situations + if (flutterNode.HasAction(ACTIONS_::kScrollUp)) { + auto flutterScrollUpAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), + flutterScrollUpAction, {}); + } else if (flutterNode.HasAction(ACTIONS_::kScrollLeft)) { + DispatchSemanticsAction(static_cast(elementId), + ACTIONS_::kScrollLeft, {}); + } else if (flutterNode.HasAction(ACTIONS_::kIncrease)) { + flutterNode.value = flutterNode.increasedValue; + flutterNode.valueAttributes = flutterNode.increasedValueAttributes; + + Flutter_SendAccessibilityAsyncEvent( + elementId, ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + DispatchSemanticsAction(static_cast(elementId), + ACTIONS_::kIncrease, {}); + } else { + } + std::string currComponetType = GetNodeComponentType(flutterNode); + if (currComponetType == "ListView") { + /** Scrolled event, sent when a scrollable component experiences a + * scroll event. 4096 */ + ArkUI_AccessibilityEventType scrollEventType1 = + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); + FML_DLOG(INFO) + << "ExecuteAccessibilityAction -> action: scroll forward(" << action + << ")" << " event: scroll forward(" << scrollEventType1 << ")"; + } + break; + } + /** Backward scroll action. 512 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: { + // flutter scroll down with different situations + if (flutterNode.HasAction(ACTIONS_::kScrollDown)) { + auto flutterScrollDownAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), + flutterScrollDownAction, {}); + } else if (flutterNode.HasAction(ACTIONS_::kScrollRight)) { + DispatchSemanticsAction(static_cast(elementId), + ACTIONS_::kScrollRight, {}); + } else if (flutterNode.HasAction(ACTIONS_::kDecrease)) { + flutterNode.value = flutterNode.decreasedValue; + flutterNode.valueAttributes = flutterNode.decreasedValueAttributes; + + Flutter_SendAccessibilityAsyncEvent( + elementId, ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + DispatchSemanticsAction(static_cast(elementId), + ACTIONS_::kDecrease, {}); + } else { + } + std::string currComponetType = GetNodeComponentType(flutterNode); + if (currComponetType == "ListView") { + /** Scrolled event, sent when a scrollable component experiences a + * scroll event. 4096 */ + ArkUI_AccessibilityEventType scrollBackwardEventType = + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + Flutter_SendAccessibilityAsyncEvent(elementId, scrollBackwardEventType); + FML_DLOG(INFO) + << "ExecuteAccessibilityAction -> action: scroll backward(" + << action << ")" << " event: scroll backward(" + << scrollBackwardEventType << ")"; + } + break; + } + /** Copy action for text content. 1024 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: copy(" << action + << ")"; + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCopy, {}); + break; + } + /** Paste action for text content. 2048 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE: { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: paste(" << action + << ")"; + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kPaste, {}); + break; + } + /** Cut action for text content. 4096 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: cut(" << action << ")"; + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCut, {}); + break; + } + /** Text selection action, requiring the setting of selectTextBegin, + * TextEnd, and TextInForward parameters to select a text + * segment in the text box. 8192 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: select text(" + << action << ")"; + // 输入框文本选择操作 + PerformSelectText(flutterNode, action, actionArguments); + break; + } + /** Text content setting action. 16384 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: set text(" + << action << ")"; + // 输入框设置文本 + PerformSetText(flutterNode, action, actionArguments); + break; + } + /** Cursor position setting action. 1048576 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION: { FML_DLOG(INFO) - << "ExecuteAccessibilityAction -> action: scroll forward(" << action - << ")" << " event: scroll forward(" << scrollEventType1 << ")"; - } - break; - } - /** Backward scroll action. 512 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: { - // flutter scroll down with different situations - if (flutterNode.HasAction(ACTIONS_::kScrollDown)) { - auto flutterScrollDownAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), - flutterScrollDownAction, {}); - } else if (flutterNode.HasAction(ACTIONS_::kScrollRight)) { - DispatchSemanticsAction(static_cast(elementId), - ACTIONS_::kScrollRight, {}); - } else if (flutterNode.HasAction(ACTIONS_::kDecrease)) { - flutterNode.value = flutterNode.decreasedValue; - flutterNode.valueAttributes = flutterNode.decreasedValueAttributes; - - Flutter_SendAccessibilityAsyncEvent( - elementId, ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); - DispatchSemanticsAction(static_cast(elementId), - ACTIONS_::kDecrease, {}); - } else { - } - std::string currComponetType = GetNodeComponentType(flutterNode); - if (currComponetType == "ListView") { - /** Scrolled event, sent when a scrollable component experiences a - * scroll event. 4096 */ - ArkUI_AccessibilityEventType scrollBackwardEventType = + << "ExecuteAccessibilityAction -> action: set cursor position(" + << action << ")"; + break; + } + /** Invalid action. 0 */ + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID: { + /** Invalid event. 0 */ + ArkUI_AccessibilityEventType invalidEventType = ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; - Flutter_SendAccessibilityAsyncEvent(elementId, scrollBackwardEventType); - FML_DLOG(INFO) - << "ExecuteAccessibilityAction -> action: scroll backward(" - << action << ")" << " event: scroll backward(" - << scrollBackwardEventType << ")"; - } - break; - } - /** Copy action for text content. 1024 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: copy(" << action - << ")"; - DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCopy, {}); - break; - } - /** Paste action for text content. 2048 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: paste(" << action - << ")"; - DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kPaste, {}); - break; - } - /** Cut action for text content. 4096 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: cut(" << action << ")"; - DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCut, {}); - break; - } - /** Text selection action, requiring the setting of selectTextBegin, - * TextEnd, and TextInForward parameters to select a text - * segment in the text box. 8192 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: select text(" - << action << ")"; - // 输入框文本选择操作 - PerformSelectText(flutterNode, action, actionArguments); - break; - } - /** Text content setting action. 16384 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: set text(" - << action << ")"; - // 输入框设置文本 - PerformSetText(flutterNode, action, actionArguments); - break; - } - /** Cursor position setting action. 1048576 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION: { - FML_DLOG(INFO) - << "ExecuteAccessibilityAction -> action: set cursor position(" - << action << ")"; - break; - } - /** Invalid action. 0 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID: { - /** Invalid event. 0 */ - ArkUI_AccessibilityEventType invalidEventType = - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_INVALID; - Flutter_SendAccessibilityAsyncEvent(elementId, invalidEventType); - FML_DLOG(ERROR) << "ExecuteAccessibilityAction -> action: invalid(" - << action << ")" << " event: innvalid(" - << invalidEventType << ")"; - break; - } - default: { - /** custom semantics action */ - } + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_INVALID; + Flutter_SendAccessibilityAsyncEvent(elementId, invalidEventType); + FML_DLOG(ERROR) << "ExecuteAccessibilityAction -> action: invalid(" + << action << ")" << " event: innvalid(" + << invalidEventType << ")"; + break; + } + default: { + /** custom semantics action */ + } } FML_DLOG(INFO) << "--- ExecuteAccessibilityAction is end ---"; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; -- Gitee From cec6d47ec454060a26362b591886d83a7d99b2b5 Mon Sep 17 00:00:00 2001 From: xi_leilei Date: Sat, 30 Nov 2024 17:17:59 +0800 Subject: [PATCH 140/151] =?UTF-8?q?windows=E5=B9=B3=E5=8F=B0=E4=B8=8B?= =?UTF-8?q?=E4=B8=8D=E7=BC=96=E8=AF=91=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xi_leilei --- BUILD.gn | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 3bed74db99..efab1e976b 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -141,7 +141,7 @@ group("unittests") { } # Compile all unittests targets if enabled. - if (enable_unittests) { + if (enable_unittests && !is_win) { public_deps += [ "//flutter/display_list:display_list_rendertests", "//flutter/display_list:display_list_unittests", @@ -170,7 +170,6 @@ group("unittests") { if (is_ohos) { public_deps += [ - "//flutter/fml/:fml_unittests", "//flutter/shell/platform/ohos:flutter_ohos_unittests", ] } -- Gitee From c39c61828c37d447ba36cd338cc0f37e309c71af Mon Sep 17 00:00:00 2001 From: xiaozn Date: Tue, 3 Dec 2024 20:32:28 +0800 Subject: [PATCH 141/151] =?UTF-8?q?fix=EF=BC=9A=E4=BF=AE=E5=A4=8D=E6=8A=98?= =?UTF-8?q?=E5=8F=A0=E5=B1=8F=E7=8A=B6=E6=80=81=E6=94=B9=E5=8F=98=E6=97=B6?= =?UTF-8?q?MediaQuery=E7=BB=84=E4=BB=B6=E8=8E=B7=E5=8F=96=E7=9A=84ohos?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xiaozn --- .../flutter/src/main/ets/view/FlutterView.ets | 98 ++++++++++--------- 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index 071aeffa81..0609078336 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -113,17 +113,17 @@ export class PlatformViewParas { } export class DisplayFeature { - bounds: Rect ; + bounds: display.Rect ; type: DisplayFeatureType; state: DisplayFeatureState; - constructor(bounds: Rect, type: DisplayFeatureType, state: DisplayFeatureState) { + constructor(bounds: display.Rect, type: DisplayFeatureType, state: DisplayFeatureState) { this.bounds = bounds; this.type = type; this.state = state; } - getBounds(): Rect { + getBounds(): display.Rect { return this.bounds; } getType(): DisplayFeatureType { @@ -133,7 +133,7 @@ export class DisplayFeature { return this.state; } - setBounds(bounds: Rect): void { + setBounds(bounds: display.Rect): void { this.bounds = bounds; } setType(type: DisplayFeatureType): void { @@ -214,48 +214,8 @@ export class FlutterView { this.displayInfo = display.getDefaultDisplaySync(); this.viewportMetrics.devicePixelRatio = this.displayInfo?.densityPixels; this.viewportMetrics.physicalTouchSlop = 1.0 * this.displayInfo?.densityPixels; - let displayClass: Array = []; - let displayFeatures: ArrayList = new ArrayList(); - let state = 0; - let type = 0; - if (display.isFoldable()) { - if (display.getFoldStatus() == 2) { - type = DisplayFeatureType.HINGE - state = DisplayFeatureState.UNKNOWN; - } else if (display.getFoldStatus() == 1) { - type = DisplayFeatureType.FOLD; - state = DisplayFeatureState.POSTURE_FLAT; - } else if (display.getFoldStatus() == 3) { - type = DisplayFeatureType.FOLD; - state = DisplayFeatureState.POSTURE_HALF_OPENED; - } else { - type = DisplayFeatureType.UNKNOWN; - state = DisplayFeatureState.UNKNOWN; - } - display.getAllDisplays((err: BusinessError, data: Array) => { - displayClass = data; - const errCode: number = err.code; - if (errCode) { - console.error(`Failed to obtain all the display objects. Code: ${err.code}, message: ${err.message}`); - return; - } - displayClass.forEach(async feature => { - let bounds = await feature.getAvailableArea(); - Log.i(TAG, `bounds is : ${JSON.stringify(bounds)}`); - displayFeatures.add(new DisplayFeature(bounds, type, state)); - }) - this.viewportMetrics.displayFeatures = displayFeatures; - }); - } else { - type = DisplayFeatureType.CUTOUT; - state = DisplayFeatureState.UNKNOWN; - let promise = this.displayInfo.getAvailableArea(); - promise.then((data) =>{ - Log.i(TAG, `bounds is : ${JSON.stringify(data)}`); - displayFeatures.add(new DisplayFeature(data, type, state)); - }) - this.viewportMetrics.displayFeatures = displayFeatures; - } + + this.buildDisplayFeatures(display.getFoldStatus()); this.mainWindow = FlutterManager.getInstance() .getWindowStage(FlutterManager.getInstance().getUIAbility(context)) @@ -266,6 +226,12 @@ export class FlutterView { this.mainWindow?.on('avoidAreaChange', this.avoidAreaChangeCallback); this.mainWindow?.on('windowStatusChange', this.windowStatusChangeCallback); + //监听折叠屏折叠状态 + display?.on('foldStatusChange', (data: display.FoldStatus)=>{ + Log.i(TAG, `fold is : ${JSON.stringify(data)}`); + this.buildDisplayFeatures(data); + }); + //监听系统无障碍服务状态改变 accessibility.on('accessibilityStateChange', (data: boolean) => { Log.i(TAG, `subscribe accessibility state change, result: ${JSON.stringify(data)}`); @@ -292,6 +258,44 @@ export class FlutterView { } } + private async buildDisplayFeatures(foldStatus : display.FoldStatus) { + let displayFeatures: ArrayList = new ArrayList(); + let bound : display.Rect; + let state = 0; + let type = 0; + const displayInfos = display.getDefaultDisplaySync(); + if (display.isFoldable()) { + Log.i(TAG, `fold is true, fold status is : ${display.getFoldStatus()}`); + if (foldStatus == DisplayFoldStatus.FOLD_STATUS_FOLDED.valueOf()) { + type = DisplayFeatureType.HINGE + state = DisplayFeatureState.UNKNOWN; + } else if (foldStatus == DisplayFoldStatus.FOLD_STATUS_EXPANDED.valueOf()) { + type = DisplayFeatureType.FOLD; + state = DisplayFeatureState.POSTURE_FLAT; + } else if (foldStatus == DisplayFoldStatus.FOLD_STATUS_HALF_FOLDED.valueOf()) { + type = DisplayFeatureType.FOLD; + state = DisplayFeatureState.POSTURE_HALF_OPENED; + } else { + type = DisplayFeatureType.UNKNOWN; + state = DisplayFeatureState.UNKNOWN; + } + const displays = await display.getAllDisplays(); + for (let i = 0; i < displays.length; i++) { + bound = await displays[i].getAvailableArea(); + displayFeatures.add(new DisplayFeature(bound, type, state)); + } + Log.i(TAG, `displayFeatures is : ${JSON.stringify(displayFeatures)}`); + this.viewportMetrics.displayFeatures = displayFeatures; + } else { + Log.i(TAG, `fold is false,fold status is : ${foldStatus}`); + type = DisplayFeatureType.CUTOUT; + state = DisplayFeatureState.UNKNOWN; + bound = await displayInfos.getAvailableArea(); + this.viewportMetrics.displayFeatures.add(new DisplayFeature(bound, type, state)); + } + this.updateViewportMetrics(); + } + private windowSizeChangeCallback = (data: window.Size) => { Log.i(TAG, "windowSizeChangeCallback w:" + data.width + ", h:" + data.height); if (this.isAttachedToFlutterEngine()) { @@ -556,7 +560,7 @@ export class FlutterView { private updateViewportMetrics(): boolean { Log.i(TAG, 'isAttachedToFlutterEngine is:' + this.isAttachedToFlutterEngine); if (this.isAttachedToFlutterEngine()) { - Log.i(TAG, 'updateViewportMetrics devicePixelRatio:' + this.viewportMetrics.devicePixelRatio) + Log.i(TAG, 'updateViewportMetrics devicePixelRatio:' + this.viewportMetrics.devicePixelRatio); const displayFeature = this.viewportMetrics.displayFeatures; let displayFeaturesBounds: number[] = new Array(displayFeature.length * 4); let displayFeaturesType: number[] = new Array(displayFeature.length); -- Gitee From 3112230e95970a3944af5609e9807eb595d91e65 Mon Sep 17 00:00:00 2001 From: liujiake Date: Tue, 3 Dec 2024 21:28:47 +0800 Subject: [PATCH 142/151] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E5=A4=9A=E5=BC=95=E6=93=8E=E7=89=B9=E6=80=A7=E7=9A=84=E5=8A=A8?= =?UTF-8?q?=E7=94=BB=E9=A1=B5=E9=9D=A2=E8=B7=B3=E8=BD=AC=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E5=90=8E=E5=8D=A1=E6=AD=BB=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- .../ohos/ohos_external_texture_gl.cpp | 40 ++++++++++++++++--- .../platform/ohos/ohos_external_texture_gl.h | 10 ++++- shell/platform/ohos/platform_view_ohos.cpp | 10 +++++ 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 894611215b..0bead82e11 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -216,17 +216,16 @@ void OHOSExternalTextureGL::Paint(PaintContext& context, bool freeze, const SkSamplingOptions& sampling) { + context_ = eglGetCurrentContext(); + display_ = eglGetCurrentDisplay(); + draw_surface_ = eglGetCurrentSurface(EGL_DRAW); + read_surface_ = eglGetCurrentSurface(EGL_READ); if (state_ == AttachmentState::detached) { FML_LOG(ERROR) << "Paint, the current status is detached"; return; } if (state_ == AttachmentState::uninitialized) { - Attach(); - if (pixelMap_ != nullptr) { - // 外接纹理图片场景 - ProducePixelMapToNativeImage(); - Update(); - } + delegate_.OnPlatformViewMarkTextureFrameAvailable(Id()); } GrGLTextureInfo textureInfo; @@ -288,6 +287,9 @@ void OHOSExternalTextureGL::OnGrContextDestroyed() void OHOSExternalTextureGL::MarkNewFrameAvailable() { FML_DLOG(INFO) << " OHOSExternalTextureGL::MarkNewFrameAvailable"; + if (state_ == AttachmentState::uninitialized) { + Attach(); + } if (state_ == AttachmentState::attached) { Update(); } @@ -306,9 +308,35 @@ void OHOSExternalTextureGL::OnTextureUnregistered() } } +bool OHOSExternalTextureGL::IsContextCurrent() { + EGLContext current_egl_context = eglGetCurrentContext(); + if (context_ != current_egl_context) { + return false; + } + EGLDisplay current_egl_display = eglGetCurrentDisplay(); + if (display_ != current_egl_display) { + return false; + } + EGLSurface draw_surface = eglGetCurrentSurface(EGL_DRAW); + if (draw_surface != draw_surface_) { + return false; + } + EGLSurface read_surface = eglGetCurrentSurface(EGL_READ); + if (read_surface != read_surface_) { + return false; + } + return true; +} + void OHOSExternalTextureGL::Update() { FML_DLOG(INFO) << "OHOSExternalTextureGL::Update, texture_name_=" << texture_name_; + if (!IsContextCurrent() && context_) { + if (eglMakeCurrent(display_, draw_surface_, read_surface_, context_) != EGL_TRUE) { + FML_LOG(WARNING) << "eglMakeCurrent in update failed"; + } + } + if (nativeImage_ == nullptr) { FML_LOG(ERROR) << "Update, nativeImage_ is nullptr, texture_name_=" << texture_name_; return; diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h index a5a3c1d5fc..ce8faf8e3f 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.h +++ b/shell/platform/ohos/ohos_external_texture_gl.h @@ -54,6 +54,7 @@ class OHOSExternalTextureGL : public flutter::Texture { bool first_update_ = false; + void Paint(PaintContext& context, const SkRect& bounds, bool freeze, @@ -100,7 +101,7 @@ class OHOSExternalTextureGL : public flutter::Texture { void ProducePixelMapToBackGroundImage(); - enum class AttachmentState { uninitialized, attached, detached }; + enum class AttachmentState { uninitialized, attached, detached, todetach }; AttachmentState state_; @@ -134,6 +135,13 @@ class OHOSExternalTextureGL : public flutter::Texture { EGLDisplay eglDisplay_; FML_DISALLOW_COPY_AND_ASSIGN(OHOSExternalTextureGL); + + void* display_; + void* draw_surface_; + void* read_surface_; + void* context_; + + bool IsContextCurrent(); }; class OhosImageFrameData { diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index 1f5fd79368..4fc99fd3d7 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -117,6 +117,15 @@ PlatformViewOHOS::PlatformViewOHOS( PlatformViewOHOS::~PlatformViewOHOS() { FML_LOG(INFO) << "PlatformViewOHOS::~PlatformViewOHOS"; + for (std::map>::iterator it = external_texture_gl_.begin(); + it != external_texture_gl_.end(); ++it) { + if (it->second != nullptr) { + OH_NativeImage_Destroy(&(it->second->nativeImage_)); + it->second->nativeImage_ = nullptr; + } + } + external_texture_gl_.clear(); + FML_LOG(INFO) << "PlatformViewOHOS::~PlatformViewOHOS finish"; } void PlatformViewOHOS::NotifyCreate( @@ -461,6 +470,7 @@ uint64_t PlatformViewOHOS::RegisterExternalTexture(int64_t texture_id) } external_texture_gl_[texture_id] = ohos_external_gl; RegisterTexture(ohos_external_gl); + MarkTextureFrameAvailable(texture_id); } return surface_id; } -- Gitee From 8eb34e99794367c1da29a7ebbd6bd74a2ecbd94c Mon Sep 17 00:00:00 2001 From: liujiake Date: Tue, 3 Dec 2024 21:59:39 +0800 Subject: [PATCH 143/151] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E5=91=8A=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- shell/platform/ohos/ohos_external_texture_gl.cpp | 3 ++- shell/platform/ohos/ohos_external_texture_gl.h | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 0bead82e11..a113f3763b 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -308,7 +308,8 @@ void OHOSExternalTextureGL::OnTextureUnregistered() } } -bool OHOSExternalTextureGL::IsContextCurrent() { +bool OHOSExternalTextureGL::IsContextCurrent() +{ EGLContext current_egl_context = eglGetCurrentContext(); if (context_ != current_egl_context) { return false; diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h index ce8faf8e3f..6e7b35e11e 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.h +++ b/shell/platform/ohos/ohos_external_texture_gl.h @@ -54,7 +54,6 @@ class OHOSExternalTextureGL : public flutter::Texture { bool first_update_ = false; - void Paint(PaintContext& context, const SkRect& bounds, bool freeze, @@ -101,7 +100,7 @@ class OHOSExternalTextureGL : public flutter::Texture { void ProducePixelMapToBackGroundImage(); - enum class AttachmentState { uninitialized, attached, detached, todetach }; + enum class AttachmentState { uninitialized, attached, detached, }; AttachmentState state_; -- Gitee From 14bf7d13bc9f4ba7803ee960ecc427566bcff9f0 Mon Sep 17 00:00:00 2001 From: xiaozn Date: Wed, 4 Dec 2024 15:07:07 +0800 Subject: [PATCH 144/151] =?UTF-8?q?fix=EF=BC=9A=E4=BF=AE=E5=A4=8D=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=90=88=E5=B9=B6=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xiaozn --- .../flutter/src/main/ets/view/FlutterView.ets | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index 0609078336..4ccd06461f 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -558,7 +558,6 @@ export class FlutterView { } private updateViewportMetrics(): boolean { - Log.i(TAG, 'isAttachedToFlutterEngine is:' + this.isAttachedToFlutterEngine); if (this.isAttachedToFlutterEngine()) { Log.i(TAG, 'updateViewportMetrics devicePixelRatio:' + this.viewportMetrics.devicePixelRatio); const displayFeature = this.viewportMetrics.displayFeatures; @@ -592,8 +591,8 @@ export class FlutterView { this.viewportMetrics.systemGestureInsetLeft, this.viewportMetrics.physicalTouchSlop, displayFeaturesBounds, - displayFeaturesState, - displayFeaturesType) + displayFeaturesType, + displayFeaturesState) return true; } return false; -- Gitee From ed6897495fe75af1059788e5206ea732be717d71 Mon Sep 17 00:00:00 2001 From: liujiake Date: Wed, 4 Dec 2024 22:45:41 +0800 Subject: [PATCH 145/151] =?UTF-8?q?=E5=A4=96=E6=8E=A5=E7=BA=B9=E7=90=86att?= =?UTF-8?q?ach=E4=B8=AD=E5=A2=9E=E5=8A=A0=E5=88=A4=E6=96=AD=EF=BC=8C?= =?UTF-8?q?=E8=8B=A5=E5=BD=93=E5=89=8Donscreen=5Fsurface=E4=B8=BA=E7=A9=BA?= =?UTF-8?q?=EF=BC=8C=E5=88=99=E7=9B=B4=E6=8E=A5=E8=BF=94=E5=9B=9E=E3=80=82?= =?UTF-8?q?=20=E8=A7=A3=E5=86=B3release=E6=A8=A1=E5=BC=8F=E4=B8=ADsurfece?= =?UTF-8?q?=E6=9C=AA=E5=87=86=E5=A4=87=E5=A5=BD=E5=B0=B1=E8=BF=9B=E8=A1=8C?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=E5=AF=BC=E8=87=B4=E7=9A=84=E9=97=AA=E9=80=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- shell/platform/ohos/ohos_external_texture_gl.cpp | 4 ++++ shell/platform/ohos/ohos_external_texture_gl.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index a113f3763b..199a20cbc6 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -160,6 +160,10 @@ void OHOSExternalTextureGL::Attach() } OHOSSurface* ohos_surface_ptr = ohos_surface_.get(); OhosSurfaceGLSkia* ohosSurfaceGLSkia_ = (OhosSurfaceGLSkia*)ohos_surface_ptr; + if (ohosSurfaceGLSkia_->GetOnscreenSurface() == nullptr) { + FML_LOG(WARNING) << "onscreen_surface_ is null, Attach failed"; + return; + } auto result = ohosSurfaceGLSkia_->GLContextMakeCurrent(); if (result->GetResult()) { FML_DLOG(INFO) << "ResourceContextMakeCurrent successed"; diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h index 6e7b35e11e..92c7edda71 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.h +++ b/shell/platform/ohos/ohos_external_texture_gl.h @@ -100,7 +100,7 @@ class OHOSExternalTextureGL : public flutter::Texture { void ProducePixelMapToBackGroundImage(); - enum class AttachmentState { uninitialized, attached, detached, }; + enum class AttachmentState { uninitialized, attached, detached }; AttachmentState state_; -- Gitee From 2c818aee1ab6a8e9934706ac44bdb7fe2574db55 Mon Sep 17 00:00:00 2001 From: liujiake Date: Thu, 5 Dec 2024 10:39:11 +0800 Subject: [PATCH 146/151] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=96=E6=8E=A5?= =?UTF-8?q?=E7=BA=B9=E7=90=86=E5=9B=BE=E7=89=87=E6=98=BE=E7=A4=BA=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- shell/platform/ohos/ohos_external_texture_gl.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 199a20cbc6..924b9bdc9d 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -291,12 +291,17 @@ void OHOSExternalTextureGL::OnGrContextDestroyed() void OHOSExternalTextureGL::MarkNewFrameAvailable() { FML_DLOG(INFO) << " OHOSExternalTextureGL::MarkNewFrameAvailable"; - if (state_ == AttachmentState::uninitialized) { - Attach(); - } if (state_ == AttachmentState::attached) { Update(); } + if (state_ == AttachmentState::uninitialized) { + Attach(); + if (pixelMap_ != nullptr) { + // 外接纹理图片场景 + ProducePixelMapToNativeImage(); + Update(); + } + } } void OHOSExternalTextureGL::OnTextureUnregistered() -- Gitee From 4d08374243df9e08bee3276be7b2659ddbc2477c Mon Sep 17 00:00:00 2001 From: liujiake Date: Thu, 5 Dec 2024 11:49:04 +0800 Subject: [PATCH 147/151] =?UTF-8?q?=E6=B6=88=E9=99=A4=E5=A4=96=E6=8E=A5?= =?UTF-8?q?=E7=BA=B9=E7=90=86=E6=89=A7=E8=A1=8C=E7=BA=BF=E7=A8=8B=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E7=9A=84=E5=BC=82=E5=B8=B8=E6=8A=A5=E9=94=99=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- shell/platform/ohos/ohos_external_texture_gl.cpp | 11 ++++++++--- shell/platform/ohos/ohos_external_texture_gl.h | 4 +++- shell/platform/ohos/platform_view_ohos.cpp | 6 +++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 924b9bdc9d..7fd3498d16 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -85,9 +85,11 @@ static bool IsPixelMapYUVFormat(PIXEL_FORMAT format) OHOSExternalTextureGL::OHOSExternalTextureGL( int64_t id, const std::shared_ptr& ohos_surface, - PlatformView::Delegate& delegate) + PlatformView::Delegate& delegate, + const TaskRunners& task_runners) : Texture(id), delegate_(delegate), + task_runners_(task_runners), ohos_surface_(std::move(ohos_surface)), transform(SkMatrix::I()) { @@ -784,8 +786,11 @@ OhosImageFrameData::~OhosImageFrameData() void OhosImageFrameData::OnPlatformViewMarkTextureFrameAvailable() { if (ohosExternalTextureGL != nullptr) { - PlatformView::Delegate& dalegate = ohosExternalTextureGL->delegate_; - dalegate.OnPlatformViewMarkTextureFrameAvailable(textureId_); + fml::TaskRunner::RunNowOrPostTask( + ohosExternalTextureGL->task_runners_.GetPlatformTaskRunner(), [textureId = textureId_, this]() { + PlatformView::Delegate& dalegate = this->ohosExternalTextureGL->delegate_; + dalegate.OnPlatformViewMarkTextureFrameAvailable(textureId); + }); } } diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h index 92c7edda71..24beb3279d 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.h +++ b/shell/platform/ohos/ohos_external_texture_gl.h @@ -40,12 +40,14 @@ class OHOSExternalTextureGL : public flutter::Texture { public: explicit OHOSExternalTextureGL(int64_t id, const std::shared_ptr& ohos_surface); explicit OHOSExternalTextureGL(int64_t id, const std::shared_ptr& ohos_surface, - PlatformView::Delegate& delegate); + PlatformView::Delegate& delegate, const TaskRunners& task_runners); ~OHOSExternalTextureGL() override; PlatformView::Delegate& delegate_; + const TaskRunners& task_runners_; + OH_NativeImage *nativeImage_; OH_NativeImage *backGroundNativeImage_; diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp index 4fc99fd3d7..b1aca3a69c 100644 --- a/shell/platform/ohos/platform_view_ohos.cpp +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -433,7 +433,7 @@ void PlatformViewOHOS::RegisterExternalTextureByImage(int64_t texture_id, iter->second->DispatchImage(image); } else { std::shared_ptr ohos_external_gl = - std::make_shared(texture_id, ohos_surface_, delegate_); + std::make_shared(texture_id, ohos_surface_, delegate_, task_runners_); external_texture_gl_[texture_id] = ohos_external_gl; RegisterTexture(ohos_external_gl); ohos_external_gl->DispatchImage(image); @@ -454,7 +454,7 @@ uint64_t PlatformViewOHOS::RegisterExternalTexture(int64_t texture_id) int ret = -1; if (ohos_context_->RenderingApi() == OHOSRenderingAPI::kOpenGLES) { std::shared_ptr ohos_external_gl = - std::make_shared(texture_id, ohos_surface_, delegate_); + std::make_shared(texture_id, ohos_surface_, delegate_, task_runners_); ohos_external_gl->nativeImage_ = OH_NativeImage_Create(texture_id, GL_TEXTURE_EXTERNAL_OES); if (ohos_external_gl->nativeImage_ == nullptr) { @@ -504,7 +504,7 @@ void PlatformViewOHOS::RegisterExternalTextureByPixelMap( iter->second->DispatchPixelMap(pixelMap); } else { std::shared_ptr ohos_external_gl = - std::make_shared(texture_id, ohos_surface_, delegate_); + std::make_shared(texture_id, ohos_surface_, delegate_, task_runners_); external_texture_gl_[texture_id] = ohos_external_gl; RegisterTexture(ohos_external_gl); ohos_external_gl->DispatchPixelMap(pixelMap); -- Gitee From 1ef956f6fd65bfac2be61e3d183aad455a3aa542 Mon Sep 17 00:00:00 2001 From: liujiake Date: Thu, 5 Dec 2024 12:17:31 +0800 Subject: [PATCH 148/151] =?UTF-8?q?=E6=9B=B4=E6=94=B9update=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E6=97=B6=E6=9C=BA=EF=BC=8C=E4=BF=AE=E5=A4=8Dwebview?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiake --- shell/platform/ohos/ohos_external_texture_gl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp index 7fd3498d16..f160e09469 100755 --- a/shell/platform/ohos/ohos_external_texture_gl.cpp +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -301,8 +301,8 @@ void OHOSExternalTextureGL::MarkNewFrameAvailable() if (pixelMap_ != nullptr) { // 外接纹理图片场景 ProducePixelMapToNativeImage(); - Update(); } + Update(); } } -- Gitee From 12e839908ef0b3682c25aa4a39491cfa78a63f8f Mon Sep 17 00:00:00 2001 From: xiaozn Date: Thu, 5 Dec 2024 19:48:28 +0800 Subject: [PATCH 149/151] =?UTF-8?q?fix=EF=BC=9A=E8=A7=A3=E5=86=B3showDialo?= =?UTF-8?q?g=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xiaozn --- .../flutter/src/main/ets/view/FlutterView.ets | 134 +----------------- 1 file changed, 3 insertions(+), 131 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index 4ccd06461f..3b893b5d52 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -27,7 +27,6 @@ import PlatformView, { Params } from '../plugin/platform/PlatformView'; import { JSON } from '@kit.ArkTS'; import { accessibility } from '@kit.AccessibilityKit'; import TextInputPlugin from '../plugin/editing/TextInputPlugin'; -import { BusinessError } from '@kit.BasicServicesKit'; const TAG = "FlutterViewTag"; @@ -48,7 +47,6 @@ export class ViewportMetrics { systemGestureInsetBottom: number = 0; systemGestureInsetLeft: number = 0; physicalTouchSlop: number = -1; - displayFeatures: ArrayList = new ArrayList(); clone(): ViewportMetrics { const copy = new ViewportMetrics(); @@ -68,7 +66,6 @@ export class ViewportMetrics { copy.systemGestureInsetBottom = this.systemGestureInsetBottom; copy.systemGestureInsetLeft = this.systemGestureInsetLeft; copy.physicalTouchSlop = this.physicalTouchSlop; - copy.displayFeatures = this.displayFeatures; return copy; } @@ -112,72 +109,6 @@ export class PlatformViewParas { } } -export class DisplayFeature { - bounds: display.Rect ; - type: DisplayFeatureType; - state: DisplayFeatureState; - - constructor(bounds: display.Rect, type: DisplayFeatureType, state: DisplayFeatureState) { - this.bounds = bounds; - this.type = type; - this.state = state; - } - - getBounds(): display.Rect { - return this.bounds; - } - getType(): DisplayFeatureType { - return this.type; - } - getState(): DisplayFeatureState { - return this.state; - } - - setBounds(bounds: display.Rect): void { - this.bounds = bounds; - } - setType(type: DisplayFeatureType): void { - this.type = type; - } - setState(state: DisplayFeatureState): void { - this.state = state; - } -} - -export class Rect { - left: number = 0.0; - top: number = 0.0; - width: number = 0.0; - height: number = 0.0; - - constructor(left: number, top: number, width: number, height: number) { - this.left = left; - this.top = top; - this.width = width; - this.height = height; - } -} - -export enum DisplayFeatureType { - UNKNOWN = 0, - FOLD = 1, - HINGE = 2, - CUTOUT = 3, -}; - -export enum DisplayFoldStatus { - FOLD_STATUS_UNKNOWN = 0, - FOLD_STATUS_EXPANDED = 1, - FOLD_STATUS_FOLDED = 2, - FOLD_STATUS_HALF_FOLDED = 3, -}; - -export enum DisplayFeatureState { - UNKNOWN = 0, - POSTURE_FLAT = 1, - POSTURE_HALF_OPENED = 2, -}; - export class FlutterView { private flutterEngine: FlutterEngine | null = null @@ -215,8 +146,6 @@ export class FlutterView { this.viewportMetrics.devicePixelRatio = this.displayInfo?.densityPixels; this.viewportMetrics.physicalTouchSlop = 1.0 * this.displayInfo?.densityPixels; - this.buildDisplayFeatures(display.getFoldStatus()); - this.mainWindow = FlutterManager.getInstance() .getWindowStage(FlutterManager.getInstance().getUIAbility(context)) .getMainWindowSync(); @@ -226,12 +155,6 @@ export class FlutterView { this.mainWindow?.on('avoidAreaChange', this.avoidAreaChangeCallback); this.mainWindow?.on('windowStatusChange', this.windowStatusChangeCallback); - //监听折叠屏折叠状态 - display?.on('foldStatusChange', (data: display.FoldStatus)=>{ - Log.i(TAG, `fold is : ${JSON.stringify(data)}`); - this.buildDisplayFeatures(data); - }); - //监听系统无障碍服务状态改变 accessibility.on('accessibilityStateChange', (data: boolean) => { Log.i(TAG, `subscribe accessibility state change, result: ${JSON.stringify(data)}`); @@ -258,44 +181,6 @@ export class FlutterView { } } - private async buildDisplayFeatures(foldStatus : display.FoldStatus) { - let displayFeatures: ArrayList = new ArrayList(); - let bound : display.Rect; - let state = 0; - let type = 0; - const displayInfos = display.getDefaultDisplaySync(); - if (display.isFoldable()) { - Log.i(TAG, `fold is true, fold status is : ${display.getFoldStatus()}`); - if (foldStatus == DisplayFoldStatus.FOLD_STATUS_FOLDED.valueOf()) { - type = DisplayFeatureType.HINGE - state = DisplayFeatureState.UNKNOWN; - } else if (foldStatus == DisplayFoldStatus.FOLD_STATUS_EXPANDED.valueOf()) { - type = DisplayFeatureType.FOLD; - state = DisplayFeatureState.POSTURE_FLAT; - } else if (foldStatus == DisplayFoldStatus.FOLD_STATUS_HALF_FOLDED.valueOf()) { - type = DisplayFeatureType.FOLD; - state = DisplayFeatureState.POSTURE_HALF_OPENED; - } else { - type = DisplayFeatureType.UNKNOWN; - state = DisplayFeatureState.UNKNOWN; - } - const displays = await display.getAllDisplays(); - for (let i = 0; i < displays.length; i++) { - bound = await displays[i].getAvailableArea(); - displayFeatures.add(new DisplayFeature(bound, type, state)); - } - Log.i(TAG, `displayFeatures is : ${JSON.stringify(displayFeatures)}`); - this.viewportMetrics.displayFeatures = displayFeatures; - } else { - Log.i(TAG, `fold is false,fold status is : ${foldStatus}`); - type = DisplayFeatureType.CUTOUT; - state = DisplayFeatureState.UNKNOWN; - bound = await displayInfos.getAvailableArea(); - this.viewportMetrics.displayFeatures.add(new DisplayFeature(bound, type, state)); - } - this.updateViewportMetrics(); - } - private windowSizeChangeCallback = (data: window.Size) => { Log.i(TAG, "windowSizeChangeCallback w:" + data.width + ", h:" + data.height); if (this.isAttachedToFlutterEngine()) { @@ -560,19 +445,6 @@ export class FlutterView { private updateViewportMetrics(): boolean { if (this.isAttachedToFlutterEngine()) { Log.i(TAG, 'updateViewportMetrics devicePixelRatio:' + this.viewportMetrics.devicePixelRatio); - const displayFeature = this.viewportMetrics.displayFeatures; - let displayFeaturesBounds: number[] = new Array(displayFeature.length * 4); - let displayFeaturesType: number[] = new Array(displayFeature.length); - let displayFeaturesState: number[] = new Array(displayFeature.length); - - for (let i = 0; i < displayFeature.length; i++) { - displayFeaturesBounds[4*i] = displayFeature[i].getBounds().left; - displayFeaturesBounds[4*i + 1] = displayFeature[i].getBounds().top; - displayFeaturesBounds[4*i + 2] = displayFeature[i].getBounds().width; - displayFeaturesBounds[4*i + 3] = displayFeature[i].getBounds().height; - displayFeaturesType[i] = displayFeature[i].getType(); - displayFeaturesState[i] = displayFeature[i].getState(); - } this?.flutterEngine?.getFlutterNapi()?.setViewportMetrics(this.viewportMetrics.devicePixelRatio, this.viewportMetrics.physicalWidth, @@ -590,9 +462,9 @@ export class FlutterView { this.viewportMetrics.systemGestureInsetBottom, this.viewportMetrics.systemGestureInsetLeft, this.viewportMetrics.physicalTouchSlop, - displayFeaturesBounds, - displayFeaturesType, - displayFeaturesState) + new Array(0), + new Array(0), + new Array(0)) return true; } return false; -- Gitee From 38a5865645c9ebd609674334d5d7c2066be39ef2 Mon Sep 17 00:00:00 2001 From: xiaozn Date: Thu, 5 Dec 2024 19:55:04 +0800 Subject: [PATCH 150/151] =?UTF-8?q?fix=EF=BC=9A=E8=A7=A3=E5=86=B3showDialo?= =?UTF-8?q?g=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xiaozn --- .../flutter_embedding/flutter/src/main/ets/view/FlutterView.ets | 2 -- 1 file changed, 2 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets index 3b893b5d52..c8b2fd6742 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/view/FlutterView.ets @@ -144,8 +144,6 @@ export class FlutterView { this.id = viewId this.displayInfo = display.getDefaultDisplaySync(); this.viewportMetrics.devicePixelRatio = this.displayInfo?.densityPixels; - this.viewportMetrics.physicalTouchSlop = 1.0 * this.displayInfo?.densityPixels; - this.mainWindow = FlutterManager.getInstance() .getWindowStage(FlutterManager.getInstance().getUIAbility(context)) .getMainWindowSync(); -- Gitee From bc73d7e6d5be8a6d310ae1b253f6b63362b24eee Mon Sep 17 00:00:00 2001 From: xiaozn Date: Thu, 5 Dec 2024 20:21:19 +0800 Subject: [PATCH 151/151] =?UTF-8?q?fix=EF=BC=9A=E4=BF=AE=E6=AD=A3readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xiaozn --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 53e171f793..16a40eda07 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,8 @@ Flutter Engine 5. 由于windows和mac、linux对换行符处理方式不同,在应用dart补丁时会造成dart vm snapshot hash结果不同,可通过以下方法获取当前snapshot hash值 +6. MediaQuery组件暂不支持displayFeatureType和displayFeatureState信息 + ```shell python xxx/src/third_party/dart/tools/make_version.py --format='{{SNAPSHOT_HASH}}' ``` -- Gitee