From f68c449009b850a206ba660162ca406259ce75dc Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 28 Aug 2024 15:46:47 +0800 Subject: [PATCH 01/82] =?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 02/82] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Enative=E5=B1=82?= =?UTF-8?q?cpp=E4=BB=A3=E7=A0=81=EF=BC=8C=E5=8C=85=E6=8B=ACplatform=5Fview?= =?UTF-8?q?=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 03/82] =?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 04/82] 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 05/82] =?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 06/82] =?UTF-8?q?=E5=AE=9E=E7=8E=B0AccessibilityChannel.et?= =?UTF-8?q?s=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 07/82] =?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 08/82] =?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 09/82] =?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 10/82] =?UTF-8?q?feat:=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=E9=83=A8=E5=88=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 --- .../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 11/82] =?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 12/82] =?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 13/82] =?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 14/82] =?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 15/82] =?UTF-8?q?feat:=E5=AE=8C=E5=96=84=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8Dbridge=E7=9A=84=E8=AF=AD=E4=B9=89=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=AE=97=E6=B3=95=E6=B5=81=E7=A8=8B=EF=BC=8C=E5=B9=B6=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0findaccessibilityinfosbyid=E6=8E=A5=E5=8F=A3=E4=BA=A4?= =?UTF-8?q?=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 16/82] =?UTF-8?q?fix:=E5=88=A0=E9=99=A4=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8Dbridge=E6=9E=84=E9=80=A0=E5=87=BD=E6=95=B0=E9=87=8C?= =?UTF-8?q?=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 17/82] =?UTF-8?q?OhosAccessibilityBridge=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=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 18/82] =?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 19/82] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8Dbridge=E7=9A=84=E5=8D=95=E4=BE=8B=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E8=8E=B7=E5=8F=96instance=E7=9A=84bug=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E5=AE=8C=E5=96=84flutter=E8=AF=AD=E4=B9=89=E6=A0=91=E5=88=B0ar?= =?UTF-8?q?kui=E8=AF=AD=E4=B9=89=E6=A0=91=E7=9A=84=E8=BD=AC=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8C=E8=8E=B7=E5=8F=96=E5=88=B0root?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E5=B9=B6=E8=A7=A6=E5=8F=91ExecuteAccessibili?= =?UTF-8?q?tyAction=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 20/82] =?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 21/82] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0nativeSetSemantics?= =?UTF-8?q?Enabled=E6=8E=A5=E5=8F=A3,=E5=B0=86=E6=97=A0=E9=9A=9C=E7=A2=8D?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E7=9B=91=E5=90=AC=E7=BB=93=E6=9E=9C=E6=A1=A5?= =?UTF-8?q?=E6=8E=A5=E5=88=B0shellholder=E4=B8=8A,=E5=AE=9E=E7=8E=B0update?= =?UTF-8?q?semantics=E6=96=B9=E6=B3=95=E7=9A=84=E5=8F=AF=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 22/82] =?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 23/82] =?UTF-8?q?feat:=E6=B7=BB=E5=8A=A0=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8Dbridge=E7=B1=BB=E4=B8=AD=E4=B8=80=E4=BA=9B=E5=8A=9F?= =?UTF-8?q?=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 24/82] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8Dbridge=E7=9A=84action=E8=A7=A3=E6=9E=90=E8=BD=AC?= =?UTF-8?q?=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 25/82] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8D=E8=AF=AD=E4=B9=89=E6=A0=91=E7=9A=84=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E7=9B=B8=E5=AF=B9=E5=9D=90=E6=A0=87=E8=BD=AC?= =?UTF-8?q?=E5=8C=96=E5=B1=8F=E5=B9=95=E7=BB=9D=E5=AF=B9=E5=9D=90=E6=A0=87?= =?UTF-8?q?=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 26/82] =?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 27/82] =?UTF-8?q?feat:=E4=BC=98=E5=8C=96=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=97=A0=E9=9A=9C=E7=A2=8D=E5=8A=9F=E8=83=BD=E9=80=BB=E8=BE=91?= =?UTF-8?q?=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 28/82] =?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 29/82] =?UTF-8?q?feat:=E5=AE=8C=E5=96=84executeAccessibili?= =?UTF-8?q?tyAction=E6=96=B9=E6=B3=95=E7=9A=84=E5=B1=8F=E5=B9=95=E5=8A=A8?= =?UTF-8?q?=E4=BD=9C=E8=A7=A3=E6=9E=90=E9=80=BB=E8=BE=91=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E4=BC=A0=E9=80=92=E7=9B=B8=E5=BA=94=E7=9A=84=E5=8A=A8=E4=BD=9C?= =?UTF-8?q?=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 30/82] =?UTF-8?q?feat:=E5=AE=9E=E7=8E=B0DispatchSemanticsA?= =?UTF-8?q?ction=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 31/82] =?UTF-8?q?feat:=E5=AE=8C=E5=96=84ExecuteAccessibili?= =?UTF-8?q?tyAction=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 32/82] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9=E8=B7=B3=E8=BD=AC?= =?UTF-8?q?=E6=96=B0=E9=A1=B5=E9=9D=A2updateSemantics=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=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 33/82] =?UTF-8?q?fix:=E8=A7=A3=E5=86=B3=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?=E5=90=8E=E5=90=AF=E5=8A=A8app=E6=97=A0=E6=B3=95=E6=84=9F?= =?UTF-8?q?=E7=9F=A5=E5=B9=B6=E8=8E=B7=E5=8F=96=E5=BD=93=E5=89=8D=E6=97=A0?= =?UTF-8?q?=E9=9A=9C=E7=A2=8D=E6=98=AF=E5=90=A6=E5=BC=80=E5=90=AF=E7=8A=B6?= =?UTF-8?q?=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 34/82] =?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 35/82] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9SetAbsoluteScreenRe?= =?UTF-8?q?ct=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 36/82] =?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 37/82] =?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 38/82] =?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 39/82] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E8=B7=AF=E7=94=B1=E8=BD=AC=E6=8D=A2=E7=9A=84flutter=E8=AF=AD?= =?UTF-8?q?=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 40/82] =?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 41/82] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E5=BD=93=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=85=B3?= =?UTF-8?q?=E9=97=AD=E6=97=B6=E6=B8=85=E7=90=86bridge=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E8=AF=AD=E4=B9=89=E6=A0=91=E7=9B=B8=E5=85=B3=E7=BC=93=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 42/82] =?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 43/82] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E8=AE=BE=E7=BD=AE=E5=88=A4=E6=96=AD=E5=92=8C?= =?UTF-8?q?=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 44/82] =?UTF-8?q?fix:=E5=AE=8C=E5=96=84=E5=8F=AF=E7=82=B9?= =?UTF-8?q?=E5=87=BB=E8=8A=82=E7=82=B9=E7=BB=84=E4=BB=B6=E7=B1=BB=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 45/82] =?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 46/82] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E8=AF=AD=E4=B9=89?= =?UTF-8?q?=E6=A0=91=E8=8A=82=E7=82=B9=E7=BB=84=E4=BB=B6=E4=B8=8D=E8=83=BD?= =?UTF-8?q?=E9=9A=8F=E6=84=8F=E6=BB=91=E5=8A=A8=E7=84=A6=E7=82=B9=E6=A1=86?= =?UTF-8?q?=E7=9A=84bug=EF=BC=8C=E5=B9=B6=E5=A2=9E=E5=8A=A0=E9=83=A8?= =?UTF-8?q?=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 47/82] =?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 48/82] =?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 49/82] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E5=B1=8F=E5=B9=95?= =?UTF-8?q?=E6=9C=97=E8=AF=BB=E7=9A=84=E7=9B=B8=E5=AF=B9-=E7=BB=9D?= =?UTF-8?q?=E5=AF=B9=E5=9D=90=E6=A0=87=E8=BD=AC=E6=8D=A2=E7=AE=97=E6=B3=95?= =?UTF-8?q?=E5=9C=A8=E6=BB=91=E5=8A=A8=E5=95=86=E5=93=81list=E6=97=B6?= =?UTF-8?q?=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 50/82] =?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 51/82] =?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 52/82] =?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 53/82] =?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 54/82] =?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 55/82] =?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 56/82] =?UTF-8?q?fix:=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=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 57/82] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8D=E5=AD=97=E4=BD=93=E7=B2=97=E7=BB=86=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 | 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 58/82] =?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 59/82] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E5=B1=9E=E6=80=A7/=E7=8A=B6=E6=80=81=E5=88=A4=E6=96=AD?= =?UTF-8?q?=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 60/82] =?UTF-8?q?fix:=E8=A7=A3=E5=86=B3=E6=BB=91=E5=8A=A8?= =?UTF-8?q?=E7=A9=BA=E8=BD=AC=E9=97=AE=E9=A2=98,=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=97=A0=E9=9A=9C=E7=A2=8D=E5=B1=8F=E5=B9=95=E6=9C=97=E8=AF=BB?= =?UTF-8?q?=E6=8C=91=E9=80=89=E9=A1=B5=E9=9D=A2=E7=BB=BF=E6=A1=86=E9=81=97?= =?UTF-8?q?=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 61/82] =?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 62/82] =?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 63/82] =?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 64/82] =?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 65/82] =?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 66/82] =?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 67/82] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E4=B8=BB=E5=8A=A8?= =?UTF-8?q?=E6=9C=97=E8=AF=BB=E8=87=AA=E5=AE=9A=E4=B9=89=E6=96=87=E5=AD=97?= =?UTF-8?q?bug=EF=BC=8C=E4=BB=A3=E7=A0=81=E5=B7=A6=E6=8B=AC=E5=8F=B7?= =?UTF-8?q?=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 68/82] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=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 9051954410fb48c8dc006e72660257ee2c91279c Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 28 Oct 2024 18:04:09 +0800 Subject: [PATCH 69/82] =?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 9443bc48199ae0aded209b3020033deeb20aa172 Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 30 Oct 2024 19:30:54 +0800 Subject: [PATCH 70/82] =?UTF-8?q?fix:=E6=97=A0=E9=9A=9C=E7=A2=8D=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=8C=96=E6=B5=8B=E8=AF=95=E8=81=94=E8=B0=83=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E5=A2=9E=E5=8A=A0setcontent=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=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 71/82] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=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 a4c84d39823ae318ff31b19ed5465e2fa90b717f Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 1 Nov 2024 16:56:02 +0800 Subject: [PATCH 72/82] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E5=8F=8D=E5=A4=8D?= =?UTF-8?q?=E5=BC=80=E5=85=B3=E5=B1=8F=E5=B9=95=E6=9C=97=E8=AF=BB=EF=BC=8C?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E7=83=AD=E5=90=AF=E5=8A=A8flutter=E9=A1=B5?= =?UTF-8?q?=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 73/82] =?UTF-8?q?fix:=E5=87=8F=E5=B0=91=E9=9D=9E=E5=B1=8F?= =?UTF-8?q?=E5=B9=95=E6=98=BE=E7=A4=BA=E5=8C=BA=E5=9F=9F=E7=9A=84=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E5=88=9B=E5=BB=BA=E9=81=8D=E5=8E=86=E5=BC=80=E9=94=80?= =?UTF-8?q?,=E5=A4=A7=E5=B9=85=E5=BA=A6=E6=8F=90=E5=8D=87=E5=B1=8F?= =?UTF-8?q?=E5=B9=95=E6=9C=97=E8=AF=BB=E6=BB=91=E5=8A=A8=E6=B5=81=E7=95=85?= =?UTF-8?q?=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 30023841f861d8f54069af7f3848792adb7cc52d Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 4 Nov 2024 15:57:15 +0800 Subject: [PATCH 74/82] =?UTF-8?q?fix:=E8=BF=87=E6=BB=A4=E9=9D=9E=E5=B1=8F?= =?UTF-8?q?=E5=B9=95=E6=98=BE=E7=A4=BA=E7=9A=84=E8=8A=82=E7=82=B9=E5=88=9B?= =?UTF-8?q?=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=E4=B8=AD?= =?UTF-8?q?=E7=BB=BF=E6=A1=86=E5=9D=90=E6=A0=87=E6=BA=A2=E5=87=BA=E5=B1=8F?= =?UTF-8?q?=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 75/82] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8D=E5=AF=BC=E8=88=AA=E7=89=B9=E5=BE=81=E5=8A=9F=E8=83=BD?= =?UTF-8?q?,=E4=BC=98=E5=8C=96=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 | 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 89eb30994048c713dbc95d7affe5529079e50bfa Mon Sep 17 00:00:00 2001 From: zjxi Date: Tue, 5 Nov 2024 17:19:39 +0800 Subject: [PATCH 76/82] =?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 552b40d63400539dda72b384432c2610a45088fc Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 7 Nov 2024 11:03:30 +0800 Subject: [PATCH 77/82] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E6=94=B9=E8=BF=9B?= =?UTF-8?q?=E7=89=88=E5=B1=82=E6=AC=A1=E9=81=8D=E5=8E=86=E7=AE=97=E6=B3=95?= =?UTF-8?q?=E6=9E=84=E5=BB=BAarkui=E6=A0=91,=E4=BB=A5=E6=8E=A5=E5=85=A5Hyp?= =?UTF-8?q?ium=E5=92=8CUIViewer=E8=87=AA=E5=8A=A8=E5=8C=96=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E6=A1=86=E6=9E=B6,=E5=AE=9E=E7=8E=B0flutter=E7=BB=84?= =?UTF-8?q?=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 52b369ffc829216b48dd6068bec3d04c7b18885a Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 13 Nov 2024 12:14:50 +0800 Subject: [PATCH 78/82] =?UTF-8?q?fix:=E5=AE=8C=E5=96=84=E6=8C=87=E9=92=88?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=8F=98=E9=87=8F=E9=94=80=E6=AF=81=E5=90=8E?= =?UTF-8?q?=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 79/82] =?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 5f5c0997168dafcd4158b0b9cad2c0c743ee68b5 Mon Sep 17 00:00:00 2001 From: zjxi Date: Thu, 14 Nov 2024 16:12:06 +0800 Subject: [PATCH 80/82] =?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 56fee94b47f2d2fc295f4b6e16dc7272a8a3d6ed Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 15 Nov 2024 12:14:50 +0800 Subject: [PATCH 81/82] =?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 82/82] =?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