From 85a68f4f48081aca2a9ca4f4e70fddd5149783f4 Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 2 Dec 2024 15:52:18 +0800 Subject: [PATCH 01/15] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8D=E6=8E=A5=E5=8F=A3=E8=B0=83=E7=94=A8=E7=9A=84=E5=85=A5?= =?UTF-8?q?=E5=8F=82=E6=8E=A5=E5=8F=A3=E5=90=8D=E6=89=93=E5=8D=B0=EF=BC=8C?= =?UTF-8?q?=E6=96=B9=E4=BE=BF=E5=AE=9A=E4=BD=8D=E9=94=99=E8=AF=AF=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E6=9D=A5=E6=BA=90?= 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_ddl.h | 4 ---- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 5bda8bfaea..d33dcc7694 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -25,18 +25,19 @@ #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/core/SkScalar.h" -#define OHOS_API_VERSION 13 #define ARKUI_SUCCEED_CODE 0 #define ARKUI_FAILED_CODE -1 #define ARKUI_BAD_PARAM_CODE -2 #define ARKUI_OOM_CODE -3 -#define ARKUI_ACCESSIBILITY_CALL_CHECK(X) \ - do { \ - int32_t RET = X; \ - if (RET != ARKUI_SUCCEED_CODE) { \ - LOGE("Failed arkui a11y function call, error code:%{public}d", RET); \ - } \ - } while (false) \ +#define FUNCTION_NAME_STR(n) #n +#define ARKUI_ACCESSIBILITY_CALL_CHECK(X) \ + do { \ + int32_t RET = X; \ + if (RET != ARKUI_SUCCEED_CODE) { \ + LOGE("Failed function %{public}s call, error code:%{public}d", \ + FUNCTION_NAME_STR(X), RET); \ + } \ + } while (false) \ namespace flutter { @@ -1930,7 +1931,7 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( ArkUI_AccessibilityEventInfo* eventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); if (eventInfo == nullptr) { FML_DLOG(ERROR) << "Flutter_SendAccessibilityAsyncEvent " - "OH_ArkUI_CreateAccessibilityEventInfo eventInfo = null"; + "OH_ArkUI_CreateAccessibilityEventInfo eventInfo = null"; return; } diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_ddl.h b/shell/platform/ohos/accessibility/ohos_accessibility_ddl.h index c5d6c32631..96d3d38468 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_ddl.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_ddl.h @@ -72,11 +72,7 @@ public: static SetReqFocusFunc DLLoadSetReqFocusFunc(const char* symbolName); static GetNativeA11yProvider DLLoadGetNativeA11yProvider(const char* symbolName); - - }; - } // namespace flutter - #endif \ No newline at end of file -- Gitee From 66abcece2bea7f03f63e7d304e4549ce26b4e91f Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 9 Dec 2024 21:25:47 +0800 Subject: [PATCH 02/15] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8Dhypium=E7=9A=84widg?= =?UTF-8?q?et+id=E7=BB=84=E4=BB=B6=E5=90=8D=E7=A7=B0=E5=8F=98=E5=8C=96?= =?UTF-8?q?=E3=80=81scroll=E7=BB=84=E4=BB=B6=E5=AD=90=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=A4=B1=E8=B4=A5=E3=80=81=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=9D=90=E6=A0=87=E6=98=A0=E5=B0=84=E7=AE=97=E6=B3=95=E3=80=81?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=BE=93=E5=85=A5=E6=A1=86=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=96=87=E5=AD=97=E5=8F=98=E5=8C=96=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=83=A8=E5=88=86=E4=BA=8B=E4=BB=B6=E5=8F=91?= =?UTF-8?q?=E9=80=81=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 758 ++++++++++-------- .../accessibility/ohos_accessibility_bridge.h | 586 +++++++------- .../accessibility/ohos_accessibility_ddl.cpp | 15 + .../accessibility/ohos_accessibility_ddl.h | 2 + 4 files changed, 739 insertions(+), 622 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index d33dcc7694..d465dd9a2d 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "flutter/fml/logging.h" #include "flutter/shell/platform/ohos/ohos_logging.h" @@ -29,7 +30,7 @@ #define ARKUI_FAILED_CODE -1 #define ARKUI_BAD_PARAM_CODE -2 #define ARKUI_OOM_CODE -3 -#define FUNCTION_NAME_STR(n) #n +#define FUNCTION_NAME_STR(func) #func #define ARKUI_ACCESSIBILITY_CALL_CHECK(X) \ do { \ int32_t RET = X; \ @@ -82,8 +83,16 @@ void OhosAccessibilityBridge::SetNativeShellHolderId(int64_t id) this->native_shell_holder_id_ = id; } +void OhosAccessibilityBridge::FlutterSemanticsTreeUpdateCallOnce() { + static std::once_flag flag; + std::call_once(flag, [this]() { + this->RequestFocusWhenPageUpdate(0); + LOGD("call once -> RequestFocusWhenPageUpdate(0)"); + }); +} /** - * 从dart侧传递到c++侧的flutter无障碍语义树节点更新过程 + * 从dart侧传递到c++侧的flutter无障碍语义树节点更新过程, + * 路由新页面、滑动页面等操作会自动触发该语义树的更新 */ void OhosAccessibilityBridge::updateSemantics( flutter::SemanticsNodeUpdates update, @@ -91,73 +100,117 @@ void OhosAccessibilityBridge::updateSemantics( { FML_DLOG(INFO) << ("OhosAccessibilityBridge::UpdateSemantics()"); - // 当flutter页面更新时,自动请求id=0节点组件获焦(滑动组件除外) + std::vector updatedFlutterNodes; + + // 当flutter页面路由更新时,自动请求id=0节点组件获焦(规避滑动组件更新干扰) if (IS_FLUTTER_NAVIGATE) { - RequestFocusWhenPageUpdate(); + RequestFocusWhenPageUpdate(0); IS_FLUTTER_NAVIGATE = false; } + // 页面状态更新事件 + Flutter_SendAccessibilityAsyncEvent(0, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); + LOGE("Flutter_SendAccessibilityAsyncEvent -> PAGE_CONTENT_UPDATE"); + /** 获取并分析每个语义节点的更新属性 */ for (auto& item : update) { // 获取当前更新的节点node - const flutter::SemanticsNode& node = item.second; + const auto& node = item.second; - // set struct SemanticsNodeExtent - auto nodeEx = SetAndGetSemanticsNodeExtent(node); + // 更新扩展的SemanticsNode信息 + auto nodeEx = UpdatetSemanticsNodeExtent(node); //print semantics node and flags info for debugging - GetSemanticsNodeDebugInfo(node); - GetSemanticsFlagsDebugInfo(node); + GetSemanticsNodeDebugInfo(nodeEx); + GetSemanticsFlagsDebugInfo(nodeEx); /** * 构建flutter无障碍语义节点树 * NOTE: 若使用g_flutterSemanticsTree.insert({node.id, node})方式 * 来添加新增的语义节点会导致已有key值自动忽略,不会更新原有key对应的value */ - g_flutterSemanticsTree[node.id] = node; - - if(!IsNodeVisible(node)) { - continue; + g_flutterSemanticsTree[nodeEx.id] = nodeEx; + + // 若当前节点为隐藏状态,则跳过 + // if (IsNodeVisible(nodeEx)) { + // continue; + // } + // 若当前节点为获焦 + if (IsNodeFocused(nodeEx)) { + inputFocusedNode = nodeEx; + } + // 若当前节点和更新前节点信息不同,则加入更新节点数组 + if (nodeEx.hadPreviousConfig) { + updatedFlutterNodes.emplace_back(nodeEx); } // 获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 - int32_t childNodeCount = node.childrenInTraversalOrder.size(); + int32_t childNodeCount = nodeEx.childrenInTraversalOrder.size(); for (int32_t i = 0; i < childNodeCount; i++) { - g_parentChildIdVec.emplace_back( - std::make_pair(node.id, node.childrenInTraversalOrder[i])); - FML_DLOG(INFO) << "UpdateSemantics parentChildIdMap -> (" << node.id - << ", " << node.childrenInTraversalOrder[i] << ")"; + g_parentChildIdVec.emplace_back(std::make_pair(nodeEx.id, nodeEx.childrenInTraversalOrder[i])); } + } - // 当滑动节点产生滑动,并执行滑动处理 - if (HasScrolled(node)) { - LOGD("UpdateSemantics -> has scrolled"); - if (OH_GetSdkApiVersion() >= 13) { - ArkUI_AccessibilityElementInfo* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = - OhosAccessibilityDDL::DLLoadCreateElemInfoFunc("OH_ArkUI_CreateAccessibilityElementInfo"); - if (OH_ArkUI_CreateAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_CreateAccessibilityElementInfo is null, %{public}s", dlerror()); - } - ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); + for (const auto& nodeEx: updatedFlutterNodes) { + // 当滑动节点产生滑动,并执行滑动处理 + if (HasScrolled(nodeEx)) { + LOGD("UpdateSemantics -> has scrolled"); + if (OH_GetSdkApiVersion() >= 13) { + ArkUI_AccessibilityElementInfo* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = + OhosAccessibilityDDL::DLLoadCreateElemInfoFunc("OH_ArkUI_CreateAccessibilityElementInfo"); + if (OH_ArkUI_CreateAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_CreateAccessibilityElementInfo is null, %{public}s", dlerror()); + } + ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); - FlutterNodeToElementInfoById(_elementInfo, static_cast(node.id)); - FlutterScrollExecution(node, _elementInfo); + FlutterNodeToElementInfoById(_elementInfo, static_cast(nodeEx.id)); + // flutter滑动组件滑动处理逻辑 + FlutterScrollExecution(nodeEx, _elementInfo); - void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = - OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); - if (OH_ArkUI_DestoryAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_DestoryAccessibilityElementInfo is null, %{public}s", dlerror()); - } - OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); - _elementInfo = nullptr; - } - } - // 判断是否触发liveRegion活动区,当前节点是否活跃 - if (node.HasFlag(FLAGS_::kIsLiveRegion)) { - FML_DLOG(INFO) << "UpdateSemantics -> LiveRegion, node.id=" << node.id; - FlutterPageUpdate(ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); - } + void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = + OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); + if (OH_ArkUI_DestoryAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_DestoryAccessibilityElementInfo is null, %{public}s", dlerror()); + } + OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); + _elementInfo = nullptr; + } + // 发送滑动事件 + // Flutter_SendAccessibilityAsyncEvent(static_cast(nodeEx.id), + // ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED); + } + + // 判断是否触发liveRegion活动区,当前节点是否活跃 + if (nodeEx.HasFlag(FLAGS_::kIsLiveRegion) && HasChangedLabel(nodeEx)) { + FML_DLOG(INFO) << "UpdateSemantics -> page content update, nodeEx.id=" << nodeEx.id; + Flutter_SendAccessibilityAsyncEvent(static_cast(nodeEx.id), + ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); + LOGD("Flutter_SendAccessibilityAsyncEvent -> PAGE_CONTENT_UPDATE"); + } + // 判断当前获焦节点和当前更新节点是否一致,若一致则选中 + // if (accessibilityFocusedNode.id == nodeEx.id && + // !nodeEx.HasPrevFlag(FLAGS_::kIsSelected) && + // nodeEx.HasFlag(FLAGS_::kIsSelected)) { + // Flutter_SendAccessibilityAsyncEvent(static_cast(nodeEx.id), + // ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + // LOGD("Flutter_SendAccessibilityAsyncEvent -> SELECTED"); + // } + + // 更新获焦节点 + // if (inputFocusedNode.id == nodeEx.id && (lastInputFocusedNode.id != inputFocusedNode.id)) { + // lastInputFocusedNode = inputFocusedNode; + // Flutter_SendAccessibilityAsyncEvent(static_cast(nodeEx.id), + // ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED); + // LOGD("Flutter_SendAccessibilityAsyncEvent -> ACCESSIBILITY_FOCUSED"); + // } + // // 当输入框文本变化时,发送文本更新事件 + // if (inputFocusedNode.id == nodeEx.id && + // IsTextField(nodeEx) && + // nodeEx.previousValue != nodeEx.value) { + // Flutter_SendAccessibilityAsyncEvent(static_cast(nodeEx.id), + // ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_TEXT_UPDATE); + // LOGD("Flutter_SendAccessibilityAsyncEvent -> TEXT_UPDATE"); + // } } // 遍历更新的actions,并将所有的actions的id添加进actionMap @@ -188,7 +241,7 @@ void OhosAccessibilityBridge::updateSemantics( * flutter可滑动组件的滑动逻辑处理实现 */ void OhosAccessibilityBridge::FlutterScrollExecution( - flutter::SemanticsNode node, + SemanticsNodeExtent node, ArkUI_AccessibilityElementInfo* elementInfoFromList) { if (OH_GetSdkApiVersion() >= 13) { @@ -219,6 +272,7 @@ void OhosAccessibilityBridge::FlutterScrollExecution( node.HasAction(ACTIONS_::kScrollDown)) { } else if (node.HasAction(ACTIONS_::kScrollLeft) || node.HasAction(ACTIONS_::kScrollRight)) { + LOGD("current flutterNode has scroll up/down/left/right"); } // 当可滑动组件存在滑动子节点 @@ -232,6 +286,15 @@ void OhosAccessibilityBridge::FlutterScrollExecution( } ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetItemCount(elementInfoFromList, itemCount)); + // 设置当前页面可见的当前选中滑动index + // int32_t currentItemIndex = node.scrollIndex; + // int32_t (*OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = + // OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex"); + // if (OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex == nullptr) { + // LOGE("OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex is null, %{public}s", dlerror()); + // } + // ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex(elementInfoFromList, currentItemIndex)); + // 设置当前页面可见的起始滑动index int32_t startItemIndex = node.scrollIndex; int32_t (*OH_ArkUI_AccessibilityElementInfoSetStartItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = @@ -274,59 +337,10 @@ void OhosAccessibilityBridge::FlutterScrollExecution( } } -/** - * 当页面内容/状态更新事件,在页面转换、切换、调整大小时发送页面状态更新事件 - */ -void OhosAccessibilityBridge::FlutterPageUpdate( - ArkUI_AccessibilityEventType eventType) -{ - if (provider_ == nullptr) { - FML_DLOG(ERROR) << "PageStateUpdate ->" - "AccessibilityProvider = nullptr"; - return; - } - if (OH_GetSdkApiVersion() >= 13) { - ArkUI_AccessibilityEventInfo* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = - OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); - if (OH_ArkUI_CreateAccessibilityEventInfo == nullptr) { - LOGE("OH_ArkUI_CreateAccessibilityEventInfo is null, %{public}s", dlerror()); - } - ArkUI_AccessibilityEventInfo* pageUpdateEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); - - int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = - OhosAccessibilityDDL::DLLoadSetEventFunc("OH_ArkUI_AccessibilityEventSetEventType"); - if (OH_ArkUI_AccessibilityEventSetEventType == nullptr) { - LOGE("OH_ArkUI_AccessibilityEventSetEventType is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityEventSetEventType(pageUpdateEventInfo, eventType) - ); - - auto callback = [](int32_t errorCode) { - FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; - }; - - void (*OH_ArkUI_SendAccessibilityAsyncEvent)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*callback)(int32_t)) = - OhosAccessibilityDDL::DLLoadSendAsyncEventFunc("OH_ArkUI_SendAccessibilityAsyncEvent"); - if (OH_ArkUI_SendAccessibilityAsyncEvent == nullptr) { - LOGE("OH_ArkUI_SendAccessibilityAsyncEvent is null, %{public}s", dlerror()); - } - OH_ArkUI_SendAccessibilityAsyncEvent(provider_, pageUpdateEventInfo, callback); - - void (*OH_ArkUI_DestoryAccessibilityEventInfo)(ArkUI_AccessibilityEventInfo*) = - OhosAccessibilityDDL::DLLoadDestroyEventFunc("OH_ArkUI_DestoryAccessibilityEventInfo"); - if (OH_ArkUI_DestoryAccessibilityEventInfo == nullptr) { - LOGE("OH_ArkUI_DestoryAccessibilityEventInfo is null, %{public}s", dlerror()); - } - OH_ArkUI_DestoryAccessibilityEventInfo(pageUpdateEventInfo); - pageUpdateEventInfo = nullptr; - } -} - /** * 特定节点的焦点请求 (当页面更新时自动请求id=0节点获焦) */ -void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() +void OhosAccessibilityBridge::RequestFocusWhenPageUpdate(int32_t requestFocusId) { if (provider_ == nullptr) { FML_DLOG(ERROR) << "RequestFocusWhenPageUpdate ->" @@ -360,7 +374,6 @@ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate() ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_REQUEST_ACCESSIBILITY_FOCUS) ); - int32_t requestFocusId = 0; int32_t (*OH_ArkUI_AccessibilityEventSetRequestFocusId)(ArkUI_AccessibilityEventInfo*, int32_t) = OhosAccessibilityDDL::DLLoadSetReqFocusFunc("OH_ArkUI_AccessibilityEventSetRequestFocusId"); if (OH_ArkUI_AccessibilityEventSetRequestFocusId == nullptr) { @@ -473,7 +486,7 @@ void OhosAccessibilityBridge::Announce(std::unique_ptr& message) } //获取根节点 -flutter::SemanticsNode OhosAccessibilityBridge::GetFlutterRootSemanticsNode() +SemanticsNodeExtent OhosAccessibilityBridge::GetFlutterRootSemanticsNode() { if (!g_flutterSemanticsTree.size()) { FML_DLOG(ERROR) @@ -491,10 +504,10 @@ flutter::SemanticsNode OhosAccessibilityBridge::GetFlutterRootSemanticsNode() /** * 根据nodeid获取或创建flutter语义节点 */ -flutter::SemanticsNode OhosAccessibilityBridge::GetFlutterSemanticsNode( +SemanticsNodeExtent OhosAccessibilityBridge::GetFlutterSemanticsNode( int32_t id) { - flutter::SemanticsNode node; + SemanticsNodeExtent node; if (g_flutterSemanticsTree.count(id) > 0) { return g_flutterSemanticsTree.at(id); FML_DLOG(INFO) << "GetFlutterSemanticsNode get node.id=" << id; @@ -518,7 +531,7 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( if (OH_GetSdkApiVersion() >= 13) { // 将flutter语义节点树传递给arkui的无障碍elementinfo for (const auto& item : g_flutterSemanticsTree) { - flutter::SemanticsNode flutterNode = item.second; + SemanticsNodeExtent flutterNode = item.second; // 创建elementinfo,系统自动加入到elementinfolist ArkUI_AccessibilityElementInfo* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = @@ -580,23 +593,25 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( // 设置孩子节点 int32_t childCount = flutterNode.childrenInTraversalOrder.size(); - auto childrenIdsVec = flutterNode.childrenInTraversalOrder; - std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); - int64_t childNodeIds[childCount]; - for (int32_t i = 0; i < childCount; i++) { - childNodeIds[i] = static_cast(childrenIdsVec[i]); - FML_DLOG(INFO) << "FlutterTreeToArkuiTree flutterNode.id= " - << flutterNode.id << " childCount= " << childCount - << " childNodeId=" << childNodeIds[i]; - } - int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = - OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); - if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); + if (childCount > 0) { + auto childrenIdsVec = flutterNode.childrenInTraversalOrder; + std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); + int64_t childNodeIds[childCount]; + for (int32_t i = 0; i < childCount; i++) { + childNodeIds[i] = static_cast(childrenIdsVec[i]); + FML_DLOG(INFO) << "FlutterTreeToArkuiTree flutterNode.id= " + << flutterNode.id << " childCount= " << childCount + << " childNodeId=" << childNodeIds[i]; + } + int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = + OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); + if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfo, childCount, childNodeIds) + ); } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfo, childCount, childNodeIds) - ); // 配置常用属性 int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = @@ -713,9 +728,8 @@ void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, { g_screenRectMap[flutterNodeId] = std::make_pair(std::make_pair(left, top), std::make_pair(right, bottom)); - FML_DLOG(INFO) << "SetAbsoluteScreenRect -> insert { " << flutterNodeId - << ", <" << left << ", " << top << ", " << right << ", " - << bottom << "> } is succeed"; + FML_DLOG(INFO) << "SetAbsoluteScreenRect -> id=" << flutterNodeId + << ", {" << left << ", " << top << ", " << right << ", "<< bottom << "> }"; } std::pair, std::pair> @@ -730,12 +744,24 @@ OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) } } +/** + * 获取flutter相对-绝对坐标映射的真实缩放系数 + */ +std::pair OhosAccessibilityBridge::GetRealScaleFactor() +{ + auto secondNode = GetFlutterSemanticsNode(1); + SkMatrix transform = secondNode.transform.asM33(); + auto scaleX = transform.get(SkMatrix::kMScaleX); + auto scaleY = transform.get(SkMatrix::kMScaleY); + return std::make_pair(scaleX, scaleY); +} + /** * flutter无障碍语义树的子节点相对坐标系转化为屏幕绝对坐标的映射算法 * 目前暂未考虑旋转、透视场景,不影响屏幕朗读功能 */ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( - flutter::SemanticsNode currNode) + SemanticsNodeExtent currNode) { // 获取当前flutter节点的相对rect auto currLeft = static_cast(currNode.rect.fLeft); @@ -743,23 +769,21 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( auto currRight = static_cast(currNode.rect.fRight); auto currBottom = static_cast(currNode.rect.fBottom); - // 获取当前flutter节点的缩放、平移、透视等矩阵坐标转换 + /** + * 获取当前flutter节点的缩放、平移、透视等矩阵坐标转换 + * 以下矩阵坐标变换参数(如:旋转/错切、透视)场景目前暂不考虑 + * NOTE: SkMatrix::kMSkewX, SkMatrix::kMSkewY, + * SkMatrix::kMPersp0, SkMatrix::kMPersp1, SkMatrix::kMPersp2 + */ SkMatrix transform = currNode.transform.asM33(); auto _kMScaleX = transform.get(SkMatrix::kMScaleX); auto _kMTransX = transform.get(SkMatrix::kMTransX); auto _kMScaleY = transform.get(SkMatrix::kMScaleY); auto _kMTransY = transform.get(SkMatrix::kMTransY); - /** 以下矩阵坐标变换参数(如:旋转/错切、透视)场景目前暂不考虑 - * NOTE: SkMatrix::kMSkewX, SkMatrix::kMSkewY, - * SkMatrix::kMPersp0, SkMatrix::kMPersp1, SkMatrix::kMPersp2 - */ // 获取当前flutter节点的父节点的相对rect int32_t parentId = GetParentId(currNode.id); auto parentNode = GetFlutterSemanticsNode(parentId); - auto parentRight = parentNode.rect.fRight; - auto parentBottom = parentNode.rect.fBottom; - // 获取当前flutter节点的父节点的绝对坐标 auto _rectPairs = GetAbsoluteScreenRect(parentNode.id); auto realParentLeft = _rectPairs.first.first; @@ -767,16 +791,19 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( auto realParentRight = _rectPairs.second.first; auto realParentBottom = _rectPairs.second.second; - // 获取root节点的绝对坐标, 即xcomponent屏幕长宽 + //获取root节点的绝对坐标 auto _rootRect = GetAbsoluteScreenRect(0); + auto rootWidth = _rootRect.second.first; auto rootHeight = _rootRect.second.second; - // 真实缩放系数 - float realScaleFactor = realParentRight / parentRight * 1.0; - float newLeft; - float newTop; - float newRight; - float newBottom; + // 获取真实缩放系数 + auto [realScaleXFactor, realScaleYFactor] = GetRealScaleFactor(); + + // 更新后的节点屏幕坐标 + float newLeft = 0.0; + float newTop = 0.0; + float newRight = 0.0; + float newBottom = 0.0; if (_kMScaleX > 1 && _kMScaleY > 1) { // 子节点相对父节点进行变化(缩放、 平移) @@ -787,42 +814,30 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( // 更新当前flutter节点currNode的相对坐标 -> 屏幕绝对坐标 SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); } else { - // 若当前节点的相对坐标与父亲节点的相对坐标值相同,则直接继承坐标值 - if (currRight == parentRight && currBottom == parentBottom) { - newLeft = realParentLeft; - newTop = realParentTop; - newRight = realParentRight; - newBottom = realParentBottom; - } else { - // 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 - newLeft = (currLeft + _kMTransX) * realScaleFactor + realParentLeft; - newTop = (currTop + _kMTransY) * realScaleFactor + realParentTop; - newRight = (currLeft + _kMTransX + currRight) * realScaleFactor + realParentLeft; - newBottom = (currTop + _kMTransY + currBottom) * realScaleFactor + realParentTop; - } - // 若子节点rect超过父节点则跳过显示(单个屏幕显示不下,滑动再重新显示) - const bool IS_OVER_SCREEN_AREA = newLeft < realParentLeft || - newTop < realParentTop || - newRight > realParentRight || - newBottom > realParentBottom || - newLeft >= newRight || - newTop >= newBottom; - if (IS_OVER_SCREEN_AREA) { - FML_DLOG(ERROR) << "ConvertChildRelativeRectToScreenRect childRect is " - "bigger than parentRect -> { nodeId: " - << currNode.id << ", (" << newLeft << ", " << newTop - << ", " << newRight << ", " << newBottom << ")}"; - // 防止滑动场景下绿框坐标超出屏幕范围,进行正则化处理 - newTop -= rootHeight; - newBottom -= rootHeight; - SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); - } else { - SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); - } + // 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 + newLeft = (currLeft + _kMTransX) * realScaleXFactor + realParentLeft; + newTop = (currTop + _kMTransY) * realScaleYFactor + realParentTop; + newRight = newLeft + currRight * realScaleXFactor; + newBottom = newTop + currBottom * realScaleYFactor; + + // 若子节点rect超过父节点则跳过显示(单个屏幕显示不下,滑动再重新显示) + const bool IS_OVER_SCREEN_AREA = newLeft < realParentLeft || newTop < realParentTop || + newRight > realParentRight || newBottom > realParentBottom || + newLeft >= newRight || newTop >= newBottom || + newRight > rootWidth || newBottom > rootHeight; + + if (IS_OVER_SCREEN_AREA) { + FML_DLOG(ERROR) << "RelativeRectToScreenRect -> childRect exceeds parentRect {Id: " + << currNode.id << ", (" << newLeft << ", " << newTop + << ", " << newRight << ", " << newBottom << ")}"; + // 防止滑动场景下绿框坐标超出屏幕范围,进行正则化处理 + // newTop = realParentBottom; + // newBottom = realParentBottom; + SetAbsoluteScreenRect(currNode.id, rootWidth, rootHeight, 0, 0); + } else { + SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); + } } - FML_DLOG(INFO) << "ConvertChildRelativeRectToScreenRect -> { nodeId: " - << currNode.id << ", (" << newLeft << ", " << newTop << ", " - << newRight << ", " << newBottom << ")}"; } /** @@ -843,7 +858,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( // 当elementId = -1或0时,创建root节点 if (elementId == 0 || elementId == -1) { // 获取flutter的root节点 - flutter::SemanticsNode flutterNode = GetFlutterSemanticsNode(static_cast(0)); + SemanticsNodeExtent flutterNode = GetFlutterSemanticsNode(static_cast(0)); // 设置elementinfo的屏幕坐标范围 int32_t left = static_cast(flutterNode.rect.fLeft); @@ -893,7 +908,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( } ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( - elementInfoFromList, flutterNode.label.empty() ? flutterNode.hint.c_str() : flutterNode.label.c_str()) + elementInfoFromList, flutterNode.label.empty() ? flutterNode.value.c_str() : flutterNode.label.c_str()) ); int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel)(ArkUI_AccessibilityElementInfo*, const char*) = @@ -916,23 +931,25 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( // 配置child节点信息 int32_t childCount = flutterNode.childrenInTraversalOrder.size(); - auto childrenIdsVec = flutterNode.childrenInTraversalOrder; - std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); - int64_t childNodeIds[childCount]; - for (int32_t i = 0; i < childCount; i++) { - childNodeIds[i] = static_cast(childrenIdsVec[i]); - FML_DLOG(INFO) - << "FlutterNodeToElementInfoById -> elementid=0 childCount=" - << childCount << " childNodeIds=" << childNodeIds[i]; - } - int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = - OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); - if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); + if (childCount > 0) { + auto childrenIdsVec = flutterNode.childrenInTraversalOrder; + std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); + int64_t childNodeIds[childCount]; + for (int32_t i = 0; i < childCount; i++) { + childNodeIds[i] = static_cast(childrenIdsVec[i]); + FML_DLOG(INFO) + << "FlutterNodeToElementInfoById -> elementid=0 childCount=" + << childCount << " childNodeIds=" << childNodeIds[i]; + } + int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = + OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); + if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds) + ); } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds) - ); // 配置root节点常用属性 int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = @@ -1006,7 +1023,8 @@ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( if (OH_ArkUI_AccessibilityElementInfoSetOperationActions == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetOperationActions is null, %{public}s", dlerror()); } - if (widget_type == "textfield") { + if (Contains(widget_type, EDIT_TEXT_WIDGET_NAME) || + Contains(widget_type, EDIT_MULTILINE_TEXT_WIDGET_NAME)) { // set elementinfo action types int32_t actionTypeNum = 10; ArkUI_AccessibleAction actions[actionTypeNum]; @@ -1054,7 +1072,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions) ); - } else if (widget_type == "scrollable") { + } else if (Contains(widget_type, SCROLL_WIDGET_NAME)) { // if node is a scrollable component int32_t actionTypeNum = 5; ArkUI_AccessibleAction actions[actionTypeNum]; @@ -1114,7 +1132,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( int64_t elementId) { if (OH_GetSdkApiVersion() >= 13) { - flutter::SemanticsNode flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); + SemanticsNodeExtent flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); // set elementinfo id int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = @@ -1175,7 +1193,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( FML_DLOG(INFO) << "FlutterNodeToElementInfoById GetParentId = " << parentId; // set accessibility text for announcing - std::string text = flutterNode.label; + std::string text = flutterNode.label + flutterNode.value; int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityText)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText"); if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityText == nullptr) { @@ -1209,23 +1227,25 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( // set chidren elementinfo ids int32_t childCount = flutterNode.childrenInTraversalOrder.size(); - auto childrenIdsVec = flutterNode.childrenInTraversalOrder; - std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); - int64_t childNodeIds[childCount]; - for (int32_t i = 0; i < childCount; i++) { - childNodeIds[i] = static_cast(childrenIdsVec[i]); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> elementid=" << elementId - << " childCount=" << childCount - << " childNodeIds=" << childNodeIds[i]; - } - int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = - OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); - if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); + if (childCount > 0) { + auto childrenIdsVec = flutterNode.childrenInTraversalOrder; + std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); + int64_t childNodeIds[childCount]; + for (int32_t i = 0; i < childCount; i++) { + childNodeIds[i] = static_cast(childrenIdsVec[i]); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> elementid=" << elementId + << " childCount=" << childCount + << " childNodeIds=" << childNodeIds[i]; + } + int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = + OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); + if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds) + ); } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds) - ); /** * 根据当前flutter节点的SemanticsFlags特性,配置对应的elmentinfo属性 @@ -1436,7 +1456,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( std::vector OhosAccessibilityBridge::GetLevelOrderTraversalTree(int32_t rootId) { std::vector levelOrderTraversalTree; - std::queue semanticsQue; + std::queue semanticsQue; auto root = GetFlutterSemanticsNode(rootId); semanticsQue.push(root); @@ -1604,6 +1624,10 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( // 获取当前elementid对应的flutter语义节点 auto flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); + // 若当前节点为非屏幕显示状态,将其显示在屏幕上 + if (!IsNodeShowOnScreen(flutterNode)) { + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kShowOnScreen, {}); + } // 根据当前elementid和无障碍动作类型,发送无障碍事件 switch (action) { @@ -1638,6 +1662,8 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( } /** Accessibility focus acquisition. 64 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: { + // 感知获焦flutter节点 + accessibilityFocusedNode = flutterNode; // 解析arkui的获焦 -> flutter对应节点的获焦 auto flutterGainFocusAction = ArkuiActionsToFlutterActions(action); DispatchSemanticsAction(static_cast(elementId), @@ -1648,11 +1674,11 @@ 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); + elementId, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); } break; } @@ -1691,19 +1717,17 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kIncrease, {}); - } else { } std::string currComponetType = GetNodeComponentType(flutterNode); - if (currComponetType == "ListView") { - /** Scrolled event, sent when a scrollable component experiences a - * scroll event. 4096 */ - ArkUI_AccessibilityEventType scrollEventType1 = - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; - Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); - FML_DLOG(INFO) - << "ExecuteAccessibilityAction -> action: scroll forward(" << action - << ")" << " event: scroll forward(" << scrollEventType1 << ")"; + if (Contains(currComponetType, SCROLL_WIDGET_NAME)) { + /** Scrolled event, sent when a scrollable component experiences a + * scroll event. 4096 */ + ArkUI_AccessibilityEventType scrollEventType1 = + ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); + FML_DLOG(INFO) + << "ExecuteAccessibilityAction -> action: scroll forward(" << action + << ")" << " event: scroll forward(" << scrollEventType1 << ")"; } break; } @@ -1726,20 +1750,17 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kDecrease, {}); - } else { } std::string currComponetType = GetNodeComponentType(flutterNode); - if (currComponetType == "ListView") { - /** Scrolled event, sent when a scrollable component experiences a - * scroll event. 4096 */ - ArkUI_AccessibilityEventType scrollBackwardEventType = - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; - Flutter_SendAccessibilityAsyncEvent(elementId, scrollBackwardEventType); - FML_DLOG(INFO) - << "ExecuteAccessibilityAction -> action: scroll backward(" - << action << ")" << " event: scroll backward(" - << scrollBackwardEventType << ")"; + if (Contains(currComponetType, SCROLL_WIDGET_NAME)) { + /** Scrolled event, sent when a scrollable component experiences a + * scroll event. 4096 */ + ArkUI_AccessibilityEventType scrollEventType1 = + ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); + FML_DLOG(INFO) + << "ExecuteAccessibilityAction -> action: scroll forward(" << action + << ")" << " event: scroll forward(" << scrollEventType1 << ")"; } break; } @@ -1943,6 +1964,7 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( } ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); FlutterNodeToElementInfoById(_elementInfo, elementId); + // 若为获焦事件,则设置当前elementinfo获焦 int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused"); @@ -2009,113 +2031,112 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( } /** - * 判断当前语义节点是否获焦 + * 设置输入框文本 */ -bool OhosAccessibilityBridge::IsNodeFocusable( - const flutter::SemanticsNode& node) -{ - if (node.HasFlag(FLAGS_::kScopesRoute)) { - return false; - } - if (node.HasFlag(FLAGS_::kIsFocusable)) { - return true; - } - // Always consider platform views focusable. - if (node.IsPlatformViewNode()) { - return true; - } - // Always consider actionable nodes focusable. - if (node.actions != 0) { - return true; - } - if ((node.flags & FOCUSABLE_FLAGS) != 0) { - return true; - } - if ((node.actions & ~FOCUSABLE_FLAGS) != 0) { - return true; - } - // Consider text nodes focusable. - return !node.label.empty() || !node.value.empty() || !node.hint.empty(); -} - void OhosAccessibilityBridge::PerformSetText( - flutter::SemanticsNode flutterNode, + SemanticsNodeExtent flutterNode, ArkUI_Accessibility_ActionType action, - ArkUI_AccessibilityActionArguments* actionArguments) {} + ArkUI_AccessibilityActionArguments* actionArguments) +{ + // 获取特殊动作参数 + int32_t (*OH_ArkUI_FindAccessibilityActionArgumentByKey)(ArkUI_AccessibilityActionArguments*, const char*, char**) = + OhosAccessibilityDDL::DLLoadGetFindActionArgs("OH_ArkUI_FindAccessibilityActionArgumentByKey"); + if (OH_ArkUI_FindAccessibilityActionArgumentByKey == nullptr) { + LOGE("OH_ArkUI_FindAccessibilityActionArgumentByKey is null, %{public}s", dlerror()); + } + const char* key_setText = "setText"; + char* newValue; + char** value = &newValue; + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key_setText, value)); + if (newValue == nullptr) { + // newValue = "888"; + LOGE("PerformSetText -> OH_ArkUI_FindAccessibilityActionArgumentByKey get null value"); + } + auto flutterSetTextAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(flutterNode.id, flutterSetTextAction, {}); + flutterNode.value = newValue; + flutterNode.valueAttributes = {}; +} +/** + * 设置文本选择范畴 + */ void OhosAccessibilityBridge::PerformSelectText( - flutter::SemanticsNode flutterNode, + SemanticsNodeExtent flutterNode, ArkUI_Accessibility_ActionType action, - ArkUI_AccessibilityActionArguments* actionArguments) {} + ArkUI_AccessibilityActionArguments* actionArguments) +{ + return; +} /** * 获取当前flutter节点的组件类型,并映射为arkui组件 */ std::string OhosAccessibilityBridge::GetNodeComponentType( - const flutter::SemanticsNode& node) + const SemanticsNodeExtent& node) { if (node.HasFlag(FLAGS_::kIsButton)) { - return "Button"; + return BUTTON_WIDGET_NAME; } if (node.HasFlag(FLAGS_::kIsTextField)) { - return "TextField"; + return EDIT_TEXT_WIDGET_NAME; } if (node.HasFlag(FLAGS_::kIsMultiline)) { - return "TextArea"; + return EDIT_MULTILINE_TEXT_WIDGET_NAME; } if (node.HasFlag(FLAGS_::kIsLink)) { - return "Link"; + return LINK_WIDGET_NAME; } if (node.HasFlag(FLAGS_::kIsSlider) || node.HasAction(ACTIONS_::kIncrease) || node.HasAction(ACTIONS_::kDecrease)) { - return "Slider"; + return SLIDER_WIDGET_NAME; } if (node.HasFlag(FLAGS_::kIsHeader)) { - return "Header"; + return HEADER_WIDGET_NAME; } if (node.HasFlag(FLAGS_::kIsImage)) { - return "Image"; + return IMAGE_WIDGET_NAME; } if (node.HasFlag(FLAGS_::kHasCheckedState)) { if (node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup)) { // arkui没有RadioButton,这里透传为RadioButton - return "RadioButton"; + return RADIO_BUTTON_WIDGET_NAME; } else { - return "Checkbox"; + return CHECK_BOX_WIDGET_NAME; } } if (node.HasFlag(FLAGS_::kHasToggledState)) { - return "Switch"; + return SWITCH_WIDGET_NAME; } if (node.HasAction(ACTIONS_::kIncrease) || node.HasAction(ACTIONS_::kDecrease)) { - return "SeekBar"; + return SEEKBAR_WIDGET_NAME; } if (node.HasFlag(FLAGS_::kHasImplicitScrolling)) { if (node.HasAction(ACTIONS_::kScrollLeft) || node.HasAction(ACTIONS_::kScrollRight)) { - return "HorizontalScrollView"; + return SCROLL_WIDGET_NAME; } else { - return "ScrollView"; + return SCROLL_WIDGET_NAME; } } if ((!node.label.empty() || !node.tooltip.empty() || !node.hint.empty())) { - return "Text"; + return TEXT_WIDGET_NAME; } - return "Widget"; + return OTHER_WIDGET_NAME; } /** * 判断当前节点是否为textfield文本框 */ -bool OhosAccessibilityBridge::IsTextField(flutter::SemanticsNode flutterNode) +bool OhosAccessibilityBridge::IsTextField(SemanticsNodeExtent flutterNode) { return flutterNode.HasFlag(FLAGS_::kIsTextField); } /** * 判断当前节点是否为滑动条slider类型 */ -bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) +bool OhosAccessibilityBridge::IsSlider(SemanticsNodeExtent flutterNode) { return flutterNode.HasFlag(FLAGS_::kIsSlider); } @@ -2123,7 +2144,7 @@ bool OhosAccessibilityBridge::IsSlider(flutter::SemanticsNode flutterNode) * 判断当前flutter节点组件是否可点击 */ bool OhosAccessibilityBridge::IsNodeClickable( - flutter::SemanticsNode flutterNode) + SemanticsNodeExtent flutterNode) { return flutterNode.HasAction(ACTIONS_::kTap); flutterNode.HasFlag(FLAGS_::kHasCheckedState) || @@ -2142,15 +2163,15 @@ bool OhosAccessibilityBridge::IsNodeClickable( * 判断当前flutter节点组件是否可显示 */ bool OhosAccessibilityBridge::IsNodeVisible( - flutter::SemanticsNode flutterNode) + SemanticsNodeExtent flutterNode) { - return flutterNode.HasFlag(FLAGS_::kIsHidden) ? false : true; + return !flutterNode.HasFlag(FLAGS_::kIsHidden); } /** * 判断当前flutter节点组件是否具备checkable属性 */ bool OhosAccessibilityBridge::IsNodeCheckable( - flutter::SemanticsNode flutterNode) + SemanticsNodeExtent flutterNode) { return flutterNode.HasFlag(FLAGS_::kHasCheckedState) || flutterNode.HasFlag(FLAGS_::kHasToggledState); @@ -2159,7 +2180,7 @@ bool OhosAccessibilityBridge::IsNodeCheckable( * 判断当前flutter节点组件是否checked/unchecked(checkbox、radio button) */ bool OhosAccessibilityBridge::IsNodeChecked( - flutter::SemanticsNode flutterNode) + SemanticsNodeExtent flutterNode) { return flutterNode.HasFlag(FLAGS_::kIsChecked) || flutterNode.HasFlag(FLAGS_::kIsToggled); @@ -2168,7 +2189,7 @@ bool OhosAccessibilityBridge::IsNodeChecked( * 判断当前flutter节点组件是否选中 */ bool OhosAccessibilityBridge::IsNodeSelected( - flutter::SemanticsNode flutterNode) + SemanticsNodeExtent flutterNode) { return flutterNode.HasFlag(FLAGS_::kIsSelected); } @@ -2176,7 +2197,7 @@ bool OhosAccessibilityBridge::IsNodeSelected( * 判断当前flutter节点组件是否为密码输入框 */ bool OhosAccessibilityBridge::IsNodePassword( - flutter::SemanticsNode flutterNode) + SemanticsNodeExtent flutterNode) { return flutterNode.HasFlag(FLAGS_::kIsTextField) && flutterNode.HasFlag(FLAGS_::kIsObscured); @@ -2185,7 +2206,7 @@ bool OhosAccessibilityBridge::IsNodePassword( * 判断当前flutter节点组件是否支持长按功能 */ bool OhosAccessibilityBridge::IsNodeHasLongPress( - flutter::SemanticsNode flutterNode) + SemanticsNodeExtent flutterNode) { return flutterNode.HasAction(ACTIONS_::kLongPress); } @@ -2193,24 +2214,81 @@ bool OhosAccessibilityBridge::IsNodeHasLongPress( * 判断当前flutter节点是否enabled */ bool OhosAccessibilityBridge::IsNodeEnabled( - flutter::SemanticsNode flutterNode) + SemanticsNodeExtent flutterNode) { return !flutterNode.HasFlag(FLAGS_::kHasEnabledState) || flutterNode.HasFlag(FLAGS_::kIsEnabled); } +/** + * 判断当前flutter节点是否在当前屏幕上显示 + */ +bool OhosAccessibilityBridge::IsNodeShowOnScreen(SemanticsNodeExtent flutterNode) +{ + return flutterNode.HasAction(ACTIONS_::kShowOnScreen); +} /** * 判断当前节点是否已经滑动 */ bool OhosAccessibilityBridge::HasScrolled( - const flutter::SemanticsNode& flutterNode) + const SemanticsNodeExtent& flutterNode) +{ + return flutterNode.scrollPosition != std::nan("") && + flutterNode.previousScrollPosition != std::nan("") && + flutterNode.previousScrollPosition != flutterNode.scrollPosition; +} +/** + * 判断当前节点是否改变标签文本 + */ +bool OhosAccessibilityBridge::HasChangedLabel(const SemanticsNodeExtent& flutterNode) +{ + if (flutterNode.label.empty() && flutterNode.previousLabel.empty()) { + return false; + } + return flutterNode.label.empty() || + flutterNode.previousLabel.empty() || + flutterNode.label != flutterNode.previousLabel; +} +/** + * 判断当前语义节点是否可获焦 + */ +bool OhosAccessibilityBridge::IsNodeFocusable( + const SemanticsNodeExtent& node) +{ + if (node.HasFlag(FLAGS_::kScopesRoute)) { + return false; + } + if (node.HasFlag(FLAGS_::kIsFocusable)) { + return true; + } + // Always consider platform views focusable. + if (node.IsPlatformViewNode()) { + return true; + } + // Always consider actionable nodes focusable. + if (node.actions != 0) { + return true; + } + if ((node.flags & FOCUSABLE_FLAGS) != 0) { + return true; + } + if ((node.actions & ~FOCUSABLE_FLAGS) != 0) { + return true; + } + // Consider text nodes focusable. + return !node.label.empty() || !node.value.empty() || !node.hint.empty(); +} +/** + * 判断当前flutter节点是否获焦 + */ +bool OhosAccessibilityBridge::IsNodeFocused(const SemanticsNodeExtent& flutterNode) { - return flutterNode.scrollPosition != std::nan(""); + return flutterNode.HasFlag(FLAGS_::kIsFocused); } /** * 判断是否可滑动 */ bool OhosAccessibilityBridge::IsNodeScrollable( - flutter::SemanticsNode flutterNode) + SemanticsNodeExtent flutterNode) { return flutterNode.HasAction(ACTIONS_::kScrollLeft) || flutterNode.HasAction(ACTIONS_::kScrollRight) || @@ -2221,14 +2299,14 @@ bool OhosAccessibilityBridge::IsNodeScrollable( * 判断当前节点组件是否是滑动组件,如: listview, gridview等 */ bool OhosAccessibilityBridge::IsScrollableWidget( - flutter::SemanticsNode flutterNode) + SemanticsNodeExtent flutterNode) { return flutterNode.HasFlag(FLAGS_::kHasImplicitScrolling); } void OhosAccessibilityBridge::AddRouteNodes( - std::vector edges, - flutter::SemanticsNode node) + std::vector edges, + SemanticsNodeExtent node) { if (node.HasFlag(FLAGS_::kScopesRoute)) { edges.emplace_back(node); @@ -2239,7 +2317,7 @@ void OhosAccessibilityBridge::AddRouteNodes( } } -std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) +std::string OhosAccessibilityBridge::GetRouteName(SemanticsNodeExtent node) { if (node.HasFlag(FLAGS_::kNamesRoute) && !node.label.empty()) { return node.label; @@ -2254,7 +2332,7 @@ std::string OhosAccessibilityBridge::GetRouteName(flutter::SemanticsNode node) return ""; } -void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) +void OhosAccessibilityBridge::onWindowNameChange(SemanticsNodeExtent route) { std::string routeName = GetRouteName(route); if (routeName.empty()) { @@ -2266,7 +2344,7 @@ void OhosAccessibilityBridge::onWindowNameChange(flutter::SemanticsNode route) } void OhosAccessibilityBridge::removeSemanticsNode( - flutter::SemanticsNode nodeToBeRemoved) + SemanticsNodeExtent nodeToBeRemoved) { if (!g_flutterSemanticsTree.size()) { FML_DLOG(ERROR) << "OhosAccessibilityBridge::removeSemanticsNode -> " @@ -2300,13 +2378,27 @@ void OhosAccessibilityBridge::ClearFlutterSemanticsCaches() } /** - * extent common struct SemanticsNode to - * derived struct SemanticsNodeExtent + * 更新扩展版flutter语义节点 */ -SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent( +SemanticsNodeExtent OhosAccessibilityBridge::UpdatetSemanticsNodeExtent( flutter::SemanticsNode node) { SemanticsNodeExtent nodeEx = SemanticsNodeExtent(); + // 获取更新前的flutter节点信息 + if (g_flutterSemanticsTree.size() > 0) { + auto prevNode = GetFlutterSemanticsNode(node.id); + nodeEx.hadPreviousConfig = true; + nodeEx.previousFlags = prevNode.flags; + nodeEx.previousActions = prevNode.actions; + nodeEx.previousTextSelectionBase = prevNode.textSelectionBase; + nodeEx.previousTextSelectionExtent = prevNode.textSelectionExtent; + nodeEx.previousScrollPosition = prevNode.scrollPosition; + nodeEx.previousScrollExtentMax = prevNode.scrollExtentMax; + nodeEx.previousScrollExtentMin = prevNode.scrollExtentMin; + nodeEx.previousValue = prevNode.value; + nodeEx.previousLabel = prevNode.label; + } + // 更新当前flutter节点信息 nodeEx.id = std::move(node.id); nodeEx.flags = std::move(node.flags); nodeEx.actions = std::move(node.actions); @@ -2334,87 +2426,93 @@ SemanticsNodeExtent OhosAccessibilityBridge::SetAndGetSemanticsNodeExtent( 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); + nodeEx.customAccessibilityActions = std::move(node.customAccessibilityActions); return nodeEx; } void OhosAccessibilityBridge::GetSemanticsNodeDebugInfo( - flutter::SemanticsNode node) + SemanticsNodeExtent 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.previousLabel=" << node.previousLabel; 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.previousFlags=" << node.previousFlags; FML_DLOG(INFO) << "node.actions=" << node.actions; + FML_DLOG(INFO) << "node.previousActions=" << node.previousActions; + FML_DLOG(INFO) << "node.value=" << node.value; + FML_DLOG(INFO) << "node.previousValue=" << node.previousValue; FML_DLOG(INFO) << "node.rect= {" << node.rect.fLeft << ", " << node.rect.fTop - << ", " << node.rect.fRight << ", " << node.rect.fBottom - << "}"; + << ", " << node.rect.fRight << ", " << node.rect.fBottom + << "}"; FML_DLOG(INFO) << "node.transform -> kMScaleX=" - << _transform.get(SkMatrix::kMScaleX); + << _transform.get(SkMatrix::kMScaleX); FML_DLOG(INFO) << "node.transform -> kMSkewX=" - << _transform.get(SkMatrix::kMSkewX); + << _transform.get(SkMatrix::kMSkewX); FML_DLOG(INFO) << "node.transform -> kMTransX=" - << _transform.get(SkMatrix::kMTransX); + << _transform.get(SkMatrix::kMTransX); FML_DLOG(INFO) << "node.transform -> kMSkewY=" - << _transform.get(SkMatrix::kMSkewY); + << _transform.get(SkMatrix::kMSkewY); FML_DLOG(INFO) << "node.transform -> kMScaleY=" - << _transform.get(SkMatrix::kMScaleY); + << _transform.get(SkMatrix::kMScaleY); FML_DLOG(INFO) << "node.transform -> kMTransY=" - << _transform.get(SkMatrix::kMTransY); + << _transform.get(SkMatrix::kMTransY); FML_DLOG(INFO) << "node.transform -> kMPersp0=" - << _transform.get(SkMatrix::kMPersp0); + << _transform.get(SkMatrix::kMPersp0); FML_DLOG(INFO) << "node.transform -> kMPersp1=" - << _transform.get(SkMatrix::kMPersp1); + << _transform.get(SkMatrix::kMPersp1); FML_DLOG(INFO) << "node.transform -> kMPersp2=" - << _transform.get(SkMatrix::kMPersp2); + << _transform.get(SkMatrix::kMPersp2); FML_DLOG(INFO) << "node.maxValueLength=" << node.maxValueLength; FML_DLOG(INFO) << "node.currentValueLength=" << node.currentValueLength; FML_DLOG(INFO) << "node.textSelectionBase=" << node.textSelectionBase; + FML_DLOG(INFO) << "node.previousTextSelectionBase=" << node.previousTextSelectionBase; FML_DLOG(INFO) << "node.textSelectionExtent=" << node.textSelectionExtent; - FML_DLOG(INFO) << "node.textSelectionBase=" << node.textSelectionBase; + FML_DLOG(INFO) << "node.previousTextSelectionExtent=" << node.previousTextSelectionExtent; 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.previousScrollPosition=" << node.previousScrollPosition; 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.previousScrollExtentMax=" << node.previousScrollExtentMax; FML_DLOG(INFO) << "node.scrollExtentMin=" << node.scrollExtentMin; + FML_DLOG(INFO) << "node.previousScrollExtentMin=" << node.previousScrollExtentMin; FML_DLOG(INFO) << "node.elevation=" << node.elevation; FML_DLOG(INFO) << "node.thickness=" << node.thickness; FML_DLOG(INFO) << "node.textDirection=" << node.textDirection; FML_DLOG(INFO) << "node.childrenInTraversalOrder.size()=" - << node.childrenInTraversalOrder.size(); + << node.childrenInTraversalOrder.size(); for (uint32_t i = 0; i < node.childrenInTraversalOrder.size(); i++) { FML_DLOG(INFO) << "node.childrenInTraversalOrder[" << i - << "]=" << node.childrenInTraversalOrder[i]; + << "]=" << node.childrenInTraversalOrder[i]; } FML_DLOG(INFO) << "node.childrenInHitTestOrder.size()=" - << 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]; + << "]=" << node.childrenInHitTestOrder[i]; } FML_DLOG(INFO) << "node.customAccessibilityActions.size()=" - << 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]; + << "]=" << node.customAccessibilityActions[i]; } FML_DLOG(INFO) << "------------------SemanticsNode-----------------"; } void OhosAccessibilityBridge::GetSemanticsFlagsDebugInfo( - flutter::SemanticsNode node) + SemanticsNodeExtent node) { FML_DLOG(INFO) << "----------------SemanticsFlags-------------------------"; FML_DLOG(INFO) << "node.id=" << node.id; diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 5f03fdc839..5240f33a75 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -32,310 +32,312 @@ typedef flutter::SemanticsFlags FLAGS_; typedef flutter::SemanticsAction ACTIONS_; struct AbsoluteRect { - float left; - float top; - float right; - float bottom; - - static constexpr AbsoluteRect MakeEmpty() { - return AbsoluteRect{0.0, 0.0, 0.0, 0.0}; - } + 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(); - int32_t previousFlags; - int32_t previousActions; - int32_t previousTextSelectionBase; - int32_t previousTextSelectionExtent; - float previousScrollPosition; - float previousScrollExtentMax; - float previousScrollExtentMin; - std::string previousValue; - std::string previousLabel; + AbsoluteRect absoluteRect = AbsoluteRect::MakeEmpty(); + int32_t parentId = -1; + bool hadPreviousConfig = false; + int32_t previousNodeId = -1; + int32_t previousFlags = 0; + int32_t previousActions = 0; + int32_t previousTextSelectionBase = -1; + int32_t previousTextSelectionExtent = -1; + double previousScrollPosition = std::nan(""); + double previousScrollExtentMax = std::nan(""); + double previousScrollExtentMin = std::nan(""); + std::string previousValue; + std::string previousLabel; + bool HasPrevAction(SemanticsAction action) const { + return (previousActions & this->actions) != 0; + } + bool HasPrevFlag(SemanticsFlags flag) const { + return (previousFlags & this->flags) != 0; + } }; /** - * flutter和ohos的无障碍服务桥接 + * 桥接flutter无障碍功能和ohos无障碍系统服务 */ class OhosAccessibilityBridge { - public: - 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_; - ArkUI_AccessibilityProvider* provider_; - - void OnOhosAccessibilityStateChange( - int64_t shellHolderId, - bool ohosAccessibilityEnabled); - - void SetNativeShellHolderId(int64_t id); - - void updateSemantics(flutter::SemanticsNodeUpdates update, - flutter::CustomAccessibilityActionUpdates actions); - - void DispatchSemanticsAction(int32_t id, - flutter::SemanticsAction action, - fml::MallocMapping args); - - void Announce(std::unique_ptr& message); - - flutter::SemanticsNode GetFlutterSemanticsNode(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 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 GetParentId(int64_t elementId); - - void ConvertChildRelativeRectToScreenRect(flutter::SemanticsNode node); - std::pair, std::pair> - GetAbsoluteScreenRect(int32_t flutterNodeId); - void SetAbsoluteScreenRect(int32_t flutterNodeId, - float left, - float top, - float right, - float bottom); - - SemanticsNodeExtent SetAndGetSemanticsNodeExtent(flutter::SemanticsNode node); - - void FlutterScrollExecution( - flutter::SemanticsNode node, - ArkUI_AccessibilityElementInfo* elementInfoFromList); - - void ClearFlutterSemanticsCaches(); - - private: - OhosAccessibilityBridge(); - static OhosAccessibilityBridge* bridgeInstance; - 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; - - flutter::SemanticsNode inputFocusedNode; - flutter::SemanticsNode lastInputFocusedNode; - flutter::SemanticsNode accessibilityFocusedNode; - - std::vector> g_parentChildIdVec; - std::map g_flutterSemanticsTree; - std::unordered_map< - int32_t, - std::pair, std::pair>> - g_screenRectMap; - std::unordered_map g_actions_mp; - std::vector g_flutterNavigationVec; - - const std::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) | - 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 FlutterSetElementInfoOperationActions( - ArkUI_AccessibilityElementInfo* elementInfoFromList, - std::string widget_type); - void FlutterTreeToArkuiTree( - ArkUI_AccessibilityElementInfoList* elementInfoList); - void BuildArkUISemanticsTree( - 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( - ArkUI_Accessibility_ActionType arkui_action); - - 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); - bool IsNodeClickable(flutter::SemanticsNode flutterNode); - 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); - bool IsScrollableWidget(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 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 FlutterPageUpdate(ArkUI_AccessibilityEventType eventType); - void RequestFocusWhenPageUpdate(); - - bool Contains(const std::string source, const std::string target); +public: + 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_; + ArkUI_AccessibilityProvider* provider_; + + void OnOhosAccessibilityStateChange( + int64_t shellHolderId, + bool ohosAccessibilityEnabled); + + void SetNativeShellHolderId(int64_t id); + + void updateSemantics(flutter::SemanticsNodeUpdates update, + flutter::CustomAccessibilityActionUpdates actions); + + void DispatchSemanticsAction(int32_t id, + flutter::SemanticsAction action, + fml::MallocMapping args); + + void Announce(std::unique_ptr& message); + + SemanticsNodeExtent GetFlutterSemanticsNode(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 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 GetParentId(int64_t elementId); + + void ConvertChildRelativeRectToScreenRect(SemanticsNodeExtent node); + std::pair, std::pair> + GetAbsoluteScreenRect(int32_t flutterNodeId); + void SetAbsoluteScreenRect(int32_t flutterNodeId, + float left, + float top, + float right, + float bottom); + + SemanticsNodeExtent UpdatetSemanticsNodeExtent(flutter::SemanticsNode node); + + void FlutterScrollExecution( + SemanticsNodeExtent node, + ArkUI_AccessibilityElementInfo* elementInfoFromList); + + void ClearFlutterSemanticsCaches(); + +private: + OhosAccessibilityBridge(); + static OhosAccessibilityBridge* bridgeInstance; + std::shared_ptr nativeAccessibilityChannel_; + std::shared_ptr accessibilityFeatures_; + + std::vector> g_parentChildIdVec; + std::map g_flutterSemanticsTree; + std::unordered_map, std::pair>> g_screenRectMap; + std::unordered_map g_actions_mp; + std::vector g_flutterNavigationVec; + + SemanticsNodeExtent inputFocusedNode; + SemanticsNodeExtent lastInputFocusedNode; + SemanticsNodeExtent accessibilityFocusedNode; + + // 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; + + const std::string OTHER_WIDGET_NAME = "View"; + const std::string TEXT_WIDGET_NAME = "Text"; + const std::string EDIT_TEXT_WIDGET_NAME = "TextInput"; + const std::string EDIT_MULTILINE_TEXT_WIDGET_NAME = "TextArea"; + const std::string IMAGE_WIDGET_NAME = "Image"; + const std::string SCROLL_WIDGET_NAME = "Scroll"; + const std::string BUTTON_WIDGET_NAME = "Button"; + const std::string LINK_WIDGET_NAME = "Link"; + const std::string SLIDER_WIDGET_NAME = "Slider"; + const std::string HEADER_WIDGET_NAME = "Header"; + const std::string RADIO_BUTTON_WIDGET_NAME = "Radio"; + const std::string CHECK_BOX_WIDGET_NAME = "Checkbox"; + const std::string SWITCH_WIDGET_NAME = "Toggle"; + const std::string SEEKBAR_WIDGET_NAME = "SeekBar"; + + const std::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) | + 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 FlutterSetElementInfoOperationActions( + ArkUI_AccessibilityElementInfo* elementInfoFromList, + std::string widget_type); + void FlutterTreeToArkuiTree( + ArkUI_AccessibilityElementInfoList* elementInfoList); + void BuildArkUISemanticsTree( + int64_t elementId, + ArkUI_AccessibilityElementInfo* elementInfoFromList, + ArkUI_AccessibilityElementInfoList* elementList); + + std::vector GetLevelOrderTraversalTree(int32_t rootId); + SemanticsNodeExtent GetFlutterRootSemanticsNode(); + std::string GetNodeComponentType(const SemanticsNodeExtent& node); + flutter::SemanticsAction ArkuiActionsToFlutterActions( + ArkUI_Accessibility_ActionType arkui_action); + + bool HasScrolled(const SemanticsNodeExtent& flutterNode); + bool HasChangedLabel(const SemanticsNodeExtent& flutterNode); + + bool IsNodeFocusable(const SemanticsNodeExtent& flutterNode); + bool IsNodeFocused(const SemanticsNodeExtent& flutterNode); + bool IsNodeCheckable(SemanticsNodeExtent flutterNode); + bool IsNodeChecked(SemanticsNodeExtent flutterNode); + bool IsNodeSelected(SemanticsNodeExtent flutterNode); + bool IsNodeClickable(SemanticsNodeExtent flutterNode); + bool IsNodeScrollable(SemanticsNodeExtent flutterNode); + bool IsNodePassword(SemanticsNodeExtent flutterNode); + bool IsNodeVisible(SemanticsNodeExtent flutterNode); + bool IsNodeEnabled(SemanticsNodeExtent flutterNode); + bool IsNodeHasLongPress(SemanticsNodeExtent flutterNode); + bool IsNodeShowOnScreen(SemanticsNodeExtent flutterNode); + + bool IsTextField(SemanticsNodeExtent flutterNode); + bool IsSlider(SemanticsNodeExtent flutterNode); + bool IsScrollableWidget(SemanticsNodeExtent flutterNode); + void PerformSetText(SemanticsNodeExtent flutterNode, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments); + void PerformSelectText(SemanticsNodeExtent flutterNode, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments); + + void AddRouteNodes(std::vector edges, + SemanticsNodeExtent node); + std::string GetRouteName(SemanticsNodeExtent node); + void onWindowNameChange(SemanticsNodeExtent route); + void removeSemanticsNode(SemanticsNodeExtent nodeToBeRemoved); + + void GetSemanticsNodeDebugInfo(SemanticsNodeExtent node); + void GetSemanticsFlagsDebugInfo(SemanticsNodeExtent node); + void GetCustomActionDebugInfo( + flutter::CustomAccessibilityAction customAccessibilityAction); + + void RequestFocusWhenPageUpdate(int32_t requestFocusId); + bool Contains(const std::string source, const std::string target); + std::pair GetRealScaleFactor(); + void FlutterSemanticsTreeUpdateCallOnce(); }; 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, + 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, + 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 diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_ddl.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_ddl.cpp index 39ea57e8a9..f4be1cadc6 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_ddl.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_ddl.cpp @@ -284,4 +284,19 @@ GetNativeA11yProvider OhosAccessibilityDDL::DLLoadGetNativeA11yProvider(const ch } return symbol; } + +GetFindActionArgs OhosAccessibilityDDL::DLLoadGetFindActionArgs(const char* symbolName) +{ + LIBHANDLE handler = LOAD_LIB(ACCESSIBILITY_LIB_NAME); + if (handler == nullptr) { + return nullptr; + } + + auto symbol = reinterpret_cast(LOAD_SYM(handler, symbolName)); + if (symbol == nullptr) { + CLOSE_LIB(handler); + return nullptr; + } + return symbol; +} } \ No newline at end of file diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_ddl.h b/shell/platform/ohos/accessibility/ohos_accessibility_ddl.h index 96d3d38468..92f27eee15 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_ddl.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_ddl.h @@ -42,6 +42,7 @@ using SetEventElemFunc = int32_t (*)(ArkUI_AccessibilityEventInfo*, ArkUI_Access using SetReqFocusFunc = int32_t (*)(ArkUI_AccessibilityEventInfo*, int32_t); using GetNativeA11yProvider = int32_t (*)(OH_NativeXComponent*, ArkUI_AccessibilityProvider**); +using GetFindActionArgs = int32_t (*)(ArkUI_AccessibilityActionArguments*, const char*, char**); class OhosAccessibilityDDL { public: @@ -72,6 +73,7 @@ public: static SetReqFocusFunc DLLoadSetReqFocusFunc(const char* symbolName); static GetNativeA11yProvider DLLoadGetNativeA11yProvider(const char* symbolName); + static GetFindActionArgs DLLoadGetFindActionArgs(const char* symbolName); }; } // namespace flutter -- Gitee From 3ce41168acb76547306c52d6c76a96c27340143a Mon Sep 17 00:00:00 2001 From: zjxi Date: Tue, 10 Dec 2024 21:07:46 +0800 Subject: [PATCH 03/15] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E9=9D=9E=E6=BB=91?= =?UTF-8?q?=E5=8A=A8=E9=A6=96=E9=A1=B5=E7=9A=84=E6=BB=91=E5=8A=A8=E5=AD=90?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E6=97=A0=E6=B3=95=E5=9C=A8uitest=E4=B8=8A?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=EF=BC=8C=E4=BC=98=E5=8C=96=E9=83=A8=E5=88=86?= =?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 | 206 +++++++----------- .../accessibility/ohos_accessibility_bridge.h | 13 +- 2 files changed, 90 insertions(+), 129 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index d465dd9a2d..35d4c5ba1d 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -131,10 +131,6 @@ void OhosAccessibilityBridge::updateSemantics( */ g_flutterSemanticsTree[nodeEx.id] = nodeEx; - // 若当前节点为隐藏状态,则跳过 - // if (IsNodeVisible(nodeEx)) { - // continue; - // } // 若当前节点为获焦 if (IsNodeFocused(nodeEx)) { inputFocusedNode = nodeEx; @@ -187,30 +183,6 @@ void OhosAccessibilityBridge::updateSemantics( ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); LOGD("Flutter_SendAccessibilityAsyncEvent -> PAGE_CONTENT_UPDATE"); } - // 判断当前获焦节点和当前更新节点是否一致,若一致则选中 - // if (accessibilityFocusedNode.id == nodeEx.id && - // !nodeEx.HasPrevFlag(FLAGS_::kIsSelected) && - // nodeEx.HasFlag(FLAGS_::kIsSelected)) { - // Flutter_SendAccessibilityAsyncEvent(static_cast(nodeEx.id), - // ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); - // LOGD("Flutter_SendAccessibilityAsyncEvent -> SELECTED"); - // } - - // 更新获焦节点 - // if (inputFocusedNode.id == nodeEx.id && (lastInputFocusedNode.id != inputFocusedNode.id)) { - // lastInputFocusedNode = inputFocusedNode; - // Flutter_SendAccessibilityAsyncEvent(static_cast(nodeEx.id), - // ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED); - // LOGD("Flutter_SendAccessibilityAsyncEvent -> ACCESSIBILITY_FOCUSED"); - // } - // // 当输入框文本变化时,发送文本更新事件 - // if (inputFocusedNode.id == nodeEx.id && - // IsTextField(nodeEx) && - // nodeEx.previousValue != nodeEx.value) { - // Flutter_SendAccessibilityAsyncEvent(static_cast(nodeEx.id), - // ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_TEXT_UPDATE); - // LOGD("Flutter_SendAccessibilityAsyncEvent -> TEXT_UPDATE"); - // } } // 遍历更新的actions,并将所有的actions的id添加进actionMap @@ -489,13 +461,11 @@ void OhosAccessibilityBridge::Announce(std::unique_ptr& message) SemanticsNodeExtent OhosAccessibilityBridge::GetFlutterRootSemanticsNode() { if (!g_flutterSemanticsTree.size()) { - FML_DLOG(ERROR) - << "GetFlutterRootSemanticsNode -> g_flutterSemanticsTree.size()=0"; + LOGE("GetFlutterRootSemanticsNode: g_flutterSemanticsTree.size()=0"); return {}; } if (g_flutterSemanticsTree.find(0) == g_flutterSemanticsTree.end()) { - FML_DLOG(ERROR) << "GetFlutterRootSemanticsNode -> g_flutterSemanticsTree " - "has no keys = 0"; + LOGE("GetFlutterRootSemanticsNod: g_flutterSemanticsTree has no root id"); return {}; } return g_flutterSemanticsTree.at(0); @@ -507,12 +477,10 @@ SemanticsNodeExtent OhosAccessibilityBridge::GetFlutterRootSemanticsNode() SemanticsNodeExtent OhosAccessibilityBridge::GetFlutterSemanticsNode( int32_t id) { - SemanticsNodeExtent node; if (g_flutterSemanticsTree.count(id) > 0) { return g_flutterSemanticsTree.at(id); - FML_DLOG(INFO) << "GetFlutterSemanticsNode get node.id=" << id; } else { - FML_DLOG(ERROR) << "GetFlutterSemanticsNode g_flutterSemanticsTree = null" << id; + LOGE("GetFlutterSemanticsNode g_flutterSemanticsTree = null"); return {}; } } @@ -720,26 +688,24 @@ int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) /** * 设置并获取xcomponet上渲染的组件的屏幕绝对坐标rect */ -void OhosAccessibilityBridge::SetAbsoluteScreenRect(int32_t flutterNodeId, +void OhosAccessibilityBridge::SetAbsoluteScreenRect(SemanticsNodeExtent& flutterNode, float left, float top, float right, float bottom) { - g_screenRectMap[flutterNodeId] = - std::make_pair(std::make_pair(left, top), std::make_pair(right, bottom)); - FML_DLOG(INFO) << "SetAbsoluteScreenRect -> id=" << flutterNodeId + g_screenRectMap[flutterNode.id] = AbsoluteRect{left, top, right, bottom}; + FML_DLOG(INFO) << "SetAbsoluteScreenRect -> id=" << flutterNode.id << ", {" << left << ", " << top << ", " << right << ", "<< bottom << "> }"; } -std::pair, std::pair> -OhosAccessibilityBridge::GetAbsoluteScreenRect(int32_t flutterNodeId) +AbsoluteRect OhosAccessibilityBridge::GetAbsoluteScreenRect(SemanticsNodeExtent& flutterNode) { - if (!g_screenRectMap.empty() && g_screenRectMap.count(flutterNodeId) > 0) { - return g_screenRectMap.at(flutterNodeId); + if (!g_screenRectMap.empty() && g_screenRectMap.count(flutterNode.id) > 0) { + return g_screenRectMap.at(flutterNode.id); } else { FML_DLOG(ERROR) << "GetAbsoluteScreenRect -> flutterNodeId=" - << flutterNodeId << " is not found !"; + << flutterNode.id << " is not found !"; return {}; } } @@ -760,7 +726,7 @@ std::pair OhosAccessibilityBridge::GetRealScaleFactor() * flutter无障碍语义树的子节点相对坐标系转化为屏幕绝对坐标的映射算法 * 目前暂未考虑旋转、透视场景,不影响屏幕朗读功能 */ -void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( +void OhosAccessibilityBridge::FlutterRelativeRectToScreenRect( SemanticsNodeExtent currNode) { // 获取当前flutter节点的相对rect @@ -784,17 +750,18 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( // 获取当前flutter节点的父节点的相对rect int32_t parentId = GetParentId(currNode.id); auto parentNode = GetFlutterSemanticsNode(parentId); + if (!g_flutterSemanticsTree.count(parentId)) { + LOGE("FlutterRelativeRectToScreenRect: GetFlutterSemanticsNode id=%{public}d null", parentId); + } + // 获取当前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; + auto [realParentLeft, realParentTop, realParentRight, realParentBottom] = GetAbsoluteScreenRect(parentNode); //获取root节点的绝对坐标 - auto _rootRect = GetAbsoluteScreenRect(0); - auto rootWidth = _rootRect.second.first; - auto rootHeight = _rootRect.second.second; + auto rootNode = GetFlutterSemanticsNode(0); + auto _rootRect = GetAbsoluteScreenRect(rootNode); + auto rootWidth = _rootRect.right; + auto rootHeight = _rootRect.bottom; // 获取真实缩放系数 auto [realScaleXFactor, realScaleYFactor] = GetRealScaleFactor(); @@ -812,7 +779,7 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( newRight = currRight * _kMScaleX; newBottom = currBottom * _kMScaleY; // 更新当前flutter节点currNode的相对坐标 -> 屏幕绝对坐标 - SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); + SetAbsoluteScreenRect(currNode, newLeft, newTop, newRight, newBottom); } else { // 子节点的屏幕绝对坐标转换,包括offset偏移值计算、缩放系数变换 newLeft = (currLeft + _kMTransX) * realScaleXFactor + realParentLeft; @@ -831,11 +798,9 @@ void OhosAccessibilityBridge::ConvertChildRelativeRectToScreenRect( << currNode.id << ", (" << newLeft << ", " << newTop << ", " << newRight << ", " << newBottom << ")}"; // 防止滑动场景下绿框坐标超出屏幕范围,进行正则化处理 - // newTop = realParentBottom; - // newBottom = realParentBottom; - SetAbsoluteScreenRect(currNode.id, rootWidth, rootHeight, 0, 0); + SetAbsoluteScreenRect(currNode, rootWidth, rootHeight, 0, 0); } else { - SetAbsoluteScreenRect(currNode.id, newLeft, newTop, newRight, newBottom); + SetAbsoluteScreenRect(currNode, newLeft, newTop, newRight, newBottom); } } } @@ -859,6 +824,9 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( if (elementId == 0 || elementId == -1) { // 获取flutter的root节点 SemanticsNodeExtent flutterNode = GetFlutterSemanticsNode(static_cast(0)); + if (flutterNode.isNull) { + LOGE("FlutterNodeToElementInfoById: GetFlutterSemanticsNode id=%{public}ld null", elementId); + } // 设置elementinfo的屏幕坐标范围 int32_t left = static_cast(flutterNode.rect.fLeft); @@ -876,11 +844,10 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( ); // 设置root节点的屏幕绝对坐标rect - SetAbsoluteScreenRect(0, left, top, right, bottom); + SetAbsoluteScreenRect(flutterNode, left, top, right, bottom); - // 设置elementinfo的action类型 - std::string widget_type = "root"; - FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); + // 设置root节点的action类型 + FlutterSetElementInfoOperationActions(elementInfoFromList, OTHER_WIDGET_NAME); // 根据flutternode信息配置对应的elementinfo int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = @@ -1133,6 +1100,9 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( { if (OH_GetSdkApiVersion() >= 13) { SemanticsNodeExtent flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); + if (flutterNode.isNull) { + LOGE("FlutterSetElementInfoProperties: GetFlutterSemanticsNode id=%{public}ld null", elementId); + } // set elementinfo id int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = @@ -1144,15 +1114,11 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, flutterNode.id) ); - // convert relative rect to absolute rect - ConvertChildRelativeRectToScreenRect(flutterNode); - auto rectPairs = GetAbsoluteScreenRect(flutterNode.id); - // set screen rect in xcomponent - int32_t left = rectPairs.first.first; - int32_t top = rectPairs.first.second; - int32_t right = rectPairs.second.first; - int32_t bottom = rectPairs.second.second; - ArkUI_AccessibleRect rect = {left, top, right, bottom}; + // 相对-绝对坐标映射 + FlutterRelativeRectToScreenRect(flutterNode); + auto [left, top, right, bottom] = GetAbsoluteScreenRect(flutterNode); + ArkUI_AccessibleRect rect = {static_cast(left), static_cast(top), + static_cast(right), static_cast(bottom)}; int32_t (*OH_ArkUI_AccessibilityElementInfoSetScreenRect)(ArkUI_AccessibilityElementInfo*, ArkUI_AccessibleRect*) = OhosAccessibilityDDL::DLLoadSetElemSreenRectFunc("OH_ArkUI_AccessibilityElementInfoSetScreenRect"); if (OH_ArkUI_AccessibilityElementInfoSetScreenRect == nullptr) { @@ -1168,19 +1134,17 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( // 配置arkui的elementinfo可操作动作属性 if (IsTextField(flutterNode)) { // 若当前flutter节点为文本输入框组件 - std::string widget_type = "textfield"; - FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); + std::string widgeType = flutterNode.HasFlag(FLAGS_::kIsMultiline) ? EDIT_MULTILINE_TEXT_WIDGET_NAME : EDIT_TEXT_WIDGET_NAME; + FlutterSetElementInfoOperationActions(elementInfoFromList, widgeType); } else if (IsScrollableWidget(flutterNode) || IsNodeScrollable(flutterNode)) { // 若当前flutter节点为可滑动组件类型 - std::string widget_type = "scrollable"; - FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); + FlutterSetElementInfoOperationActions(elementInfoFromList, SCROLL_WIDGET_NAME); } else { // 若当前flutter节点为通用组件 - std::string widget_type = "common"; - FlutterSetElementInfoOperationActions(elementInfoFromList, widget_type); + FlutterSetElementInfoOperationActions(elementInfoFromList, OTHER_WIDGET_NAME); } - // set current elementinfo parent id + // 设置当前节点的父节点id int32_t parentId = GetParentId(elementId); int32_t (*OH_ArkUI_AccessibilityElementInfoSetParentId)(ArkUI_AccessibilityElementInfo*, int32_t) = OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetParentId"); @@ -1192,7 +1156,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( ); FML_DLOG(INFO) << "FlutterNodeToElementInfoById GetParentId = " << parentId; - // set accessibility text for announcing + // 设置可朗读文本 std::string text = flutterNode.label + flutterNode.value; int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityText)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText"); @@ -1202,10 +1166,9 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfoFromList, text.c_str()) ); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetAccessibilityText = " - << text; + FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetAccessibilityText = " << text; - //set contents (same as AccessibilityText) + // 设置无障碍content文本 int32_t (*OH_ArkUI_AccessibilityElementInfoSetContents)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetContents"); if (OH_ArkUI_AccessibilityElementInfoSetContents == nullptr) { @@ -1214,7 +1177,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, text.c_str()) ); - + // 设置hint提示文本 std::string hint = flutterNode.hint; int32_t (*OH_ArkUI_AccessibilityElementInfoSetHintText)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetHintText"); @@ -1225,7 +1188,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( OH_ArkUI_AccessibilityElementInfoSetHintText(elementInfoFromList, hint.c_str()) ); - // set chidren elementinfo ids + // 设置当前节点的全部孩子节点 int32_t childCount = flutterNode.childrenInTraversalOrder.size(); if (childCount > 0) { auto childrenIdsVec = flutterNode.childrenInTraversalOrder; @@ -1497,18 +1460,19 @@ void OhosAccessibilityBridge::BuildArkUISemanticsTree( for (int64_t i = 1; i < elementInfoCount; i++) { int64_t levelOrderId = levelOrderTreeVec[i]; auto newNode = GetFlutterSemanticsNode(levelOrderId); + if (g_flutterSemanticsTree.count(newNode.id)) { + LOGE("BuildArkUISemanticsTree: GetFlutterSemanticsNode id=%{public}ld null", levelOrderId); + } //当节点为隐藏状态时,自动规避 - if (IsNodeVisible(newNode)) { - ArkUI_AccessibilityElementInfo* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = - OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); - if (OH_ArkUI_AddAndGetAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_AddAndGetAccessibilityElementInfo is null, %{public}s", dlerror()); - } - ArkUI_AccessibilityElementInfo* newElementInfo = - OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); - //配置当前子节点信息 - FlutterNodeToElementInfoById(newElementInfo, levelOrderId); + ArkUI_AccessibilityElementInfo* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = + OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); + if (OH_ArkUI_AddAndGetAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_AddAndGetAccessibilityElementInfo is null, %{public}s", dlerror()); } + ArkUI_AccessibilityElementInfo* newElementInfo = + OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + //配置当前子节点信息 + FlutterNodeToElementInfoById(newElementInfo, levelOrderId); } } } @@ -1537,6 +1501,13 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( FML_DLOG(INFO) << "FindAccessibilityNodeInfosById elementList is null"; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } + + // 获取当前对应id的flutter节点,若为空则返回错误编码 + auto flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); + if (!g_flutterSemanticsTree.count(flutterNode.id)) { + LOGE("FindAccessibilityNodeInfosById: GetFlutterSemanticsNode id=%{public}ld is null", elementId); + } + // 开启无障碍导航功能 if(elementId == -1 || elementId == 0) { accessibilityFeatures_->SetAccessibleNavigation(true, native_shell_holder_id_); @@ -1556,9 +1527,6 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } - // 过滤非当前屏幕显示的语义节点创建、配置,防止溢出屏幕坐标绘制bug以及优化性能开销 - auto flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); - if (mode == ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { /** Search for current nodes. (mode = 0) */ BuildArkUISemanticsTree(elementId, elementInfoFromList, elementList); @@ -1624,6 +1592,10 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( // 获取当前elementid对应的flutter语义节点 auto flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); + if (!g_flutterSemanticsTree.count(flutterNode.id)) { + LOGE("ExecuteAccessibilityAction: GetFlutterSemanticsNode id=%{public}ld is null", elementId); + } + // 若当前节点为非屏幕显示状态,将其显示在屏幕上 if (!IsNodeShowOnScreen(flutterNode)) { DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kShowOnScreen, {}); @@ -2039,22 +2011,22 @@ void OhosAccessibilityBridge::PerformSetText( ArkUI_AccessibilityActionArguments* actionArguments) { // 获取特殊动作参数 - int32_t (*OH_ArkUI_FindAccessibilityActionArgumentByKey)(ArkUI_AccessibilityActionArguments*, const char*, char**) = - OhosAccessibilityDDL::DLLoadGetFindActionArgs("OH_ArkUI_FindAccessibilityActionArgumentByKey"); - if (OH_ArkUI_FindAccessibilityActionArgumentByKey == nullptr) { - LOGE("OH_ArkUI_FindAccessibilityActionArgumentByKey is null, %{public}s", dlerror()); - } - const char* key_setText = "setText"; - char* newValue; - char** value = &newValue; - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key_setText, value)); - if (newValue == nullptr) { - // newValue = "888"; - LOGE("PerformSetText -> OH_ArkUI_FindAccessibilityActionArgumentByKey get null value"); - } + // int32_t (*OH_ArkUI_FindAccessibilityActionArgumentByKey)(ArkUI_AccessibilityActionArguments*, const char*, char**) = + // OhosAccessibilityDDL::DLLoadGetFindActionArgs("OH_ArkUI_FindAccessibilityActionArgumentByKey"); + // if (OH_ArkUI_FindAccessibilityActionArgumentByKey == nullptr) { + // LOGE("OH_ArkUI_FindAccessibilityActionArgumentByKey is null, %{public}s", dlerror()); + // } + // const char* key_setText = "setText"; + // char* newValue = "debug"; + // char** value = &newValue; + // ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key_setText, value)); + // if (newValue == nullptr) { + // // newValue = "888"; + // LOGE("PerformSetText -> OH_ArkUI_FindAccessibilityActionArgumentByKey get null value"); + // } auto flutterSetTextAction = ArkuiActionsToFlutterActions(action); DispatchSemanticsAction(flutterNode.id, flutterSetTextAction, {}); - flutterNode.value = newValue; + flutterNode.value = "debug"; flutterNode.valueAttributes = {}; } @@ -2147,17 +2119,6 @@ bool OhosAccessibilityBridge::IsNodeClickable( SemanticsNodeExtent 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节点组件是否可显示 @@ -2399,6 +2360,7 @@ SemanticsNodeExtent OhosAccessibilityBridge::UpdatetSemanticsNodeExtent( nodeEx.previousLabel = prevNode.label; } // 更新当前flutter节点信息 + nodeEx.isNull = false; nodeEx.id = std::move(node.id); nodeEx.flags = std::move(node.flags); nodeEx.actions = std::move(node.actions); diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 5240f33a75..8342130bff 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -41,6 +41,7 @@ struct AbsoluteRect { } }; struct SemanticsNodeExtent : flutter::SemanticsNode { + bool isNull = false; AbsoluteRect absoluteRect = AbsoluteRect::MakeEmpty(); int32_t parentId = -1; bool hadPreviousConfig = false; @@ -131,10 +132,9 @@ public: int64_t elementId); int32_t GetParentId(int64_t elementId); - void ConvertChildRelativeRectToScreenRect(SemanticsNodeExtent node); - std::pair, std::pair> - GetAbsoluteScreenRect(int32_t flutterNodeId); - void SetAbsoluteScreenRect(int32_t flutterNodeId, + void FlutterRelativeRectToScreenRect(SemanticsNodeExtent node); + AbsoluteRect GetAbsoluteScreenRect(SemanticsNodeExtent& flutterNode); + void SetAbsoluteScreenRect(SemanticsNodeExtent& flutterNode, float left, float top, float right, @@ -156,8 +156,7 @@ private: std::vector> g_parentChildIdVec; std::map g_flutterSemanticsTree; - std::unordered_map, std::pair>> g_screenRectMap; + std::unordered_map g_screenRectMap; std::unordered_map g_actions_mp; std::vector g_flutterNavigationVec; @@ -167,7 +166,7 @@ private: // 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 RET_ERROR_STATE_CODE = -1; 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 d460c9dc0056e36d33a8ef7e79aac7509d0bb3db Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 11 Dec 2024 15:37:54 +0800 Subject: [PATCH 04/15] =?UTF-8?q?fix:=E4=BC=98=E5=8C=96=E6=97=A0=E9=9A=9C?= =?UTF-8?q?=E7=A2=8D=E9=83=A8=E5=88=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 --- .../ohos_accessibility_bridge.cpp | 70 +++++++------------ .../accessibility/ohos_accessibility_bridge.h | 2 + 2 files changed, 28 insertions(+), 44 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 35d4c5ba1d..2b9f261cd9 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -83,13 +83,6 @@ void OhosAccessibilityBridge::SetNativeShellHolderId(int64_t id) this->native_shell_holder_id_ = id; } -void OhosAccessibilityBridge::FlutterSemanticsTreeUpdateCallOnce() { - static std::once_flag flag; - std::call_once(flag, [this]() { - this->RequestFocusWhenPageUpdate(0); - LOGD("call once -> RequestFocusWhenPageUpdate(0)"); - }); -} /** * 从dart侧传递到c++侧的flutter无障碍语义树节点更新过程, * 路由新页面、滑动页面等操作会自动触发该语义树的更新 @@ -108,9 +101,9 @@ void OhosAccessibilityBridge::updateSemantics( IS_FLUTTER_NAVIGATE = false; } - // 页面状态更新事件 + // 页面内容更新事件 Flutter_SendAccessibilityAsyncEvent(0, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); - LOGE("Flutter_SendAccessibilityAsyncEvent -> PAGE_CONTENT_UPDATE"); + LOGD("Flutter_SendAccessibilityAsyncEvent -> PAGE_CONTENT_UPDATE"); /** 获取并分析每个语义节点的更新属性 */ for (auto& item : update) { @@ -147,6 +140,7 @@ void OhosAccessibilityBridge::updateSemantics( } } + /* 针对更新后的节点进行事件处理 */ for (const auto& nodeEx: updatedFlutterNodes) { // 当滑动节点产生滑动,并执行滑动处理 if (HasScrolled(nodeEx)) { @@ -171,11 +165,8 @@ void OhosAccessibilityBridge::updateSemantics( OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); _elementInfo = nullptr; } - // 发送滑动事件 - // Flutter_SendAccessibilityAsyncEvent(static_cast(nodeEx.id), - // ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED); } - + // 判断是否触发liveRegion活动区,当前节点是否活跃 if (nodeEx.HasFlag(FLAGS_::kIsLiveRegion) && HasChangedLabel(nodeEx)) { FML_DLOG(INFO) << "UpdateSemantics -> page content update, nodeEx.id=" << nodeEx.id; @@ -185,28 +176,9 @@ void OhosAccessibilityBridge::updateSemantics( } } - // 遍历更新的actions,并将所有的actions的id添加进actionMap - for (const auto& item : actions) { - const flutter::CustomAccessibilityAction action = item.second; - GetCustomActionDebugInfo(action); - g_actions_mp[action.id] = action; - } - // 打印flutter语义树的不同节点的属性信息 - for (const auto& item : g_flutterSemanticsTree) { - FML_DLOG(INFO) << "g_flutterSemanticsTree -> {" << item.first << ", " - << item.second.id << "}"; - } - for (const auto& item : g_parentChildIdVec) { - FML_DLOG(INFO) << "g_parentChildIdVec -> (" << item.first << ", " - << item.second << ")"; - } - //打印按层次遍历排序的flutter语义树节点id数组 - std::vector levelOrderTraversalTree = GetLevelOrderTraversalTree(0); - for (const auto& item: levelOrderTraversalTree) { - FML_DLOG(INFO) << "LevelOrderTraversalTree: { " << item << " }"; - } - - FML_DLOG(INFO) << "=== UpdateSemantics is end ==="; + // 输出flutter语义树相关重要语义信息debug日志 + GetSemanticsDebugInfo(); + FML_DLOG(INFO) << "=== UpdateSemantics() is finished ==="; } /** @@ -258,15 +230,6 @@ void OhosAccessibilityBridge::FlutterScrollExecution( } ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetItemCount(elementInfoFromList, itemCount)); - // 设置当前页面可见的当前选中滑动index - // int32_t currentItemIndex = node.scrollIndex; - // int32_t (*OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = - // OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex"); - // if (OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex == nullptr) { - // LOGE("OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex is null, %{public}s", dlerror()); - // } - // ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex(elementInfoFromList, currentItemIndex)); - // 设置当前页面可见的起始滑动index int32_t startItemIndex = node.scrollIndex; int32_t (*OH_ArkUI_AccessibilityElementInfoSetStartItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = @@ -2528,4 +2491,23 @@ void OhosAccessibilityBridge::GetSemanticsFlagsDebugInfo( << customAccessibilityAction.hint; FML_DLOG(INFO) << "------------CustomAccessibilityAction--------------"; } + +void OhosAccessibilityBridge::GetSemanticsDebugInfo() +{ + // 打印flutter语义树的不同节点的属性信息 + for (const auto& item : g_flutterSemanticsTree) { + FML_DLOG(INFO) << "g_flutterSemanticsTree -> {" << item.first << ", " + << item.second.id << "}"; + } + for (const auto& item : g_parentChildIdVec) { + FML_DLOG(INFO) << "g_parentChildIdVec -> (" << item.first << ", " + << item.second << ")"; + } + //打印按层次遍历排序的flutter语义树节点id数组 + std::vector levelOrderTraversalTree = GetLevelOrderTraversalTree(0); + for (const auto& item: levelOrderTraversalTree) { + FML_DLOG(INFO) << "LevelOrderTraversalTree: { " << item << " }"; + } +} + } // namespace flutter diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 8342130bff..445093c0c9 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -284,6 +284,8 @@ private: bool Contains(const std::string source, const std::string target); std::pair GetRealScaleFactor(); void FlutterSemanticsTreeUpdateCallOnce(); + + void GetSemanticsDebugInfo(); }; enum class AccessibilityAction : int32_t { -- Gitee From 347c97a09db10c9af62166525cd435f63cb949e6 Mon Sep 17 00:00:00 2001 From: zjxi Date: Fri, 13 Dec 2024 16:20:26 +0800 Subject: [PATCH 05/15] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E5=AD=97=E9=87=8D?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E6=94=AF=E6=8C=81=E5=A4=9A=E7=B2=92=E5=BA=A6?= =?UTF-8?q?=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- attachment/repos/skia.patch | 1526 +++++++++++++++++++++++++++++++---- 1 file changed, 1377 insertions(+), 149 deletions(-) diff --git a/attachment/repos/skia.patch b/attachment/repos/skia.patch index adad9f220a..d85176705f 100644 --- a/attachment/repos/skia.patch +++ b/attachment/repos/skia.patch @@ -1,5 +1,5 @@ diff --git a/BUILD.gn b/BUILD.gn -index ebbd898ec9..015bb75414 100644 +index ebbd898ec9..2d4257e8d7 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -26,16 +26,21 @@ import("gn/ios.gni") @@ -142,22 +142,16 @@ index ebbd898ec9..015bb75414 100644 ] if (!skia_enable_winuwp) { -@@ -1566,6 +1619,14 @@ skia_component("skia") { - } +@@ -1559,7 +1612,7 @@ skia_component("skia") { + ] } -+ if (is_ohos) { -+ sources += [ "src/ports/SkDebug_ohos.cpp" ] -+ if (skia_use_egl) { -+ libs += [ "GLESv2" ] -+ } -+ libs += [ "hilog_ndk.z" ] -+ } -+ - if (is_mac) { - public += [ "include/ports/SkCFObject.h" ] - sources += [ -@@ -1962,7 +2023,7 @@ if (skia_enable_tools) { +- if (is_linux || is_wasm) { ++ if (is_linux || is_wasm || is_ohos) { + sources += [ "src/ports/SkDebug_stdio.cpp" ] + if (skia_use_egl) { + libs += [ "GLESv2" ] +@@ -1962,7 +2015,7 @@ if (skia_enable_tools) { if (is_android || skia_use_egl) { sources += [ "tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp" ] libs += [ "EGL" ] @@ -166,7 +160,7 @@ index ebbd898ec9..015bb75414 100644 sources += [ "tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp" ] libs += [ "GLU", -@@ -2281,7 +2342,7 @@ if (skia_enable_tools) { +@@ -2281,7 +2334,7 @@ if (skia_enable_tools) { ] } @@ -175,7 +169,7 @@ index ebbd898ec9..015bb75414 100644 if (skia_enable_skottie) { test_app("skottie_tool") { deps = [ "modules/skottie:tool" ] -@@ -2777,7 +2838,7 @@ if (skia_enable_tools) { +@@ -2777,7 +2830,7 @@ if (skia_enable_tools) { "tools/sk_app/android/surface_glue_android.h", ] libs += [ "android" ] @@ -184,7 +178,7 @@ index ebbd898ec9..015bb75414 100644 sources += [ "tools/SkGetExecutablePath_linux.cpp", "tools/sk_app/unix/RasterWindowContext_unix.cpp", -@@ -2830,7 +2891,7 @@ if (skia_enable_tools) { +@@ -2830,7 +2883,7 @@ if (skia_enable_tools) { sources += [ "tools/sk_app/GLWindowContext.h" ] if (is_android) { sources += [ "tools/sk_app/android/GLWindowContext_android.cpp" ] @@ -193,7 +187,7 @@ index ebbd898ec9..015bb75414 100644 sources += [ "tools/sk_app/unix/GLWindowContext_unix.cpp" ] } else if (is_win) { sources += [ "tools/sk_app/win/GLWindowContext_win.cpp" ] -@@ -2855,7 +2916,7 @@ if (skia_enable_tools) { +@@ -2855,7 +2908,7 @@ if (skia_enable_tools) { sources += [ "tools/sk_app/VulkanWindowContext.h" ] if (is_android) { sources += [ "tools/sk_app/android/VulkanWindowContext_android.cpp" ] @@ -202,7 +196,7 @@ index ebbd898ec9..015bb75414 100644 sources += [ "tools/sk_app/unix/VulkanWindowContext_unix.cpp" ] libs += [ "X11-xcb" ] } else if (is_win) { -@@ -2887,7 +2948,7 @@ if (skia_enable_tools) { +@@ -2887,7 +2940,7 @@ if (skia_enable_tools) { if (skia_use_dawn) { sources += [ "tools/sk_app/DawnWindowContext.cpp" ] sources += [ "tools/sk_app/DawnWindowContext.h" ] @@ -211,7 +205,7 @@ index ebbd898ec9..015bb75414 100644 if (dawn_enable_vulkan) { sources += [ "tools/sk_app/unix/DawnVulkanWindowContext_unix.cpp" ] defines = [ "VK_USE_PLATFORM_XCB_KHR" ] -@@ -2931,7 +2992,7 @@ if (skia_enable_tools) { +@@ -2931,7 +2984,7 @@ if (skia_enable_tools) { } } @@ -220,7 +214,7 @@ index ebbd898ec9..015bb75414 100644 test_app("fiddle_examples") { sources = [ "tools/fiddle/all_examples.cpp", -@@ -3088,7 +3149,7 @@ if (skia_enable_tools) { +@@ -3088,7 +3141,7 @@ if (skia_enable_tools) { } } @@ -333,21 +327,6 @@ index b43526fe1f..fb34289da7 100644 ldflags = [ "-rdynamic", "-Wl,-rpath,\$ORIGIN", -diff --git a/src/core/SkRRect.cpp b/src/core/SkRRect.cpp -index bdcf607d04..2e92ed05f3 100644 ---- a/src/core/SkRRect.cpp -+++ b/src/core/SkRRect.cpp -@@ -231,8 +231,8 @@ bool SkRRect::scaleRadii() { - double scale = 1.0; - - // The sides of the rectangle may be larger than a float. -- double width = (double)fRect.fRight - (double)fRect.fLeft; -- double height = (double)fRect.fBottom - (double)fRect.fTop; -+ double width = (double)(fRect.fRight - fRect.fLeft); -+ double height = (double)(fRect.fBottom - fRect.fTop); - scale = compute_min_scale(fRadii[0].fX, fRadii[1].fX, width, scale); - scale = compute_min_scale(fRadii[1].fY, fRadii[2].fY, height, scale); - scale = compute_min_scale(fRadii[2].fX, fRadii[3].fX, width, scale); diff --git a/src/gpu/ganesh/gl/egl/GrGLMakeEGLInterface.cpp b/src/gpu/ganesh/gl/egl/GrGLMakeEGLInterface.cpp index 78225b4610..c2105852b1 100644 --- a/src/gpu/ganesh/gl/egl/GrGLMakeEGLInterface.cpp @@ -1091,57 +1070,19 @@ index 0000000000..eb318dc3a3 +#endif + +#endif /* __gl2platform_h_ */ -diff --git a/src/ports/SkDebug_ohos.cpp b/src/ports/SkDebug_ohos.cpp -new file mode 100644 -index 0000000000..0e5e0829b6 ---- /dev/null -+++ b/src/ports/SkDebug_ohos.cpp -@@ -0,0 +1,32 @@ -+// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved -+// Use of this source code is governed by a BSD-style license that can be -+// found in the LICENSE file. -+ -+#include "include/core/SkTypes.h" -+ -+#include -+#include -+ -+ -+#ifdef HILOG_LOG_DOMAIN -+ #undef HILOG_LOG_DOMAIN -+#endif -+ -+#ifdef HILOG_LOG_TAG -+ #undef HILOG_LOG_DOMAIN -+#endif -+ -+ -+#define HILOG_LOG_DOMAIN 0x0000 -+#define HILOG_LOG_TAG "Skia" -+ -+void SkDebugf(const char format[], ...) { -+ char outStr[1024] = { 0 }; -+ va_list args; -+ va_start(args, format); -+ (void)vsnprintf(outStr,sizeof(outStr), format, args); -+ va_end(args); -+ -+ (void)OH_LOG_Print(LOG_APP, LOG_INFO, HILOG_LOG_DOMAIN,\ -+ HILOG_LOG_TAG, "%{public}s", outStr); -+} diff --git a/src/ports/skia_ohos/FontConfig_ohos.cpp b/src/ports/skia_ohos/FontConfig_ohos.cpp new file mode 100644 -index 0000000000..2dfc1348c1 +index 0000000000..c502ed853e --- /dev/null +++ b/src/ports/skia_ohos/FontConfig_ohos.cpp -@@ -0,0 +1,1312 @@ +@@ -0,0 +1,1308 @@ +// Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "FontConfig_ohos.h" + -+#include ++#include +#include +#include +#include @@ -1197,10 +1138,6 @@ index 0000000000..2dfc1348c1 + */ +int FontConfig_OHOS::getFamilyCount() const +{ -+#if ENABLE_DEBUG -+ dumpGeneric(); -+ dumpFallback(); -+#endif + return genericFamilySet.size(); +} + @@ -1553,7 +1490,7 @@ index 0000000000..2dfc1348c1 + */ +void FontConfig_OHOS::dumpFont(const FontInfo& font) const +{ -+ SkDEBUGF("name=%s, family=%s, weight=%d, width=%d, slant=%d, index=%d", ++ LOGI("name=%s, family=%s, weight=%d, width=%d, slant=%d, index=%d", + font.fname.c_str(), font.familyName.c_str(), font.style.weight(), font.style.width(), font.style.slant(), + font.index); + int count = font.axisSet.axis.size(); @@ -1565,7 +1502,7 @@ index 0000000000..2dfc1348c1 + str.append(","); + } + } -+ SkDEBUGF("axis={%s}\n", str.c_str()); ++ LOGI("axis={%s}\n", str.c_str()); + } +} + @@ -1573,9 +1510,9 @@ index 0000000000..2dfc1348c1 + */ +void FontConfig_OHOS::dumpGeneric() const +{ -+ SkDEBUGF("\n"); ++ LOGI("\n"); + for (unsigned int i = 0; i < genericFamilySet.size(); i++) { -+ SkDEBUGF("[%d] familyName : %s - %d\n", i, genericFamilySet[i]->familyName.c_str(), ++ LOGI("[%d] familyName : %s - %d\n", i, genericFamilySet[i]->familyName.c_str(), + static_cast(genericFamilySet[i]->typefaceSet->size())); + for (int j = 0; j < genericFamilySet[i]->typefaceSet->size(); j++) { + if ((*(genericFamilySet[i]->typefaceSet))[j].get()) { @@ -1583,10 +1520,10 @@ index 0000000000..2dfc1348c1 + if (font) { + dumpFont(*font); + } else { -+ SkDEBUGF("font [%d] is null\n", j); ++ LOGE("font [%d] is null\n", j); + } + } else { -+ SkDEBUGF("typefeace [%d] is null\n", j); ++ LOGE("typefeace [%d] is null\n", j); + } + } + } @@ -1596,21 +1533,21 @@ index 0000000000..2dfc1348c1 + */ +void FontConfig_OHOS::dumpFallback() const +{ -+ SkDEBUGF("\n"); ++ LOGI("\n"); + int count = 0; + fallbackForMap.foreach([this, &count](const SkString& key, + const FallbackSetPos& setIndex) { -+ SkDEBUGF("[%d] family : %s - %d\n", count++, key.c_str(), setIndex.count); ++ LOGI("[%d] family : %s - %d\n", count++, key.c_str(), setIndex.count); + for (unsigned int i = setIndex.index; i < setIndex.index + setIndex.count; i++) { + const TypefaceSet& tpSet = *(fallbackSet[i]->typefaceSet.get()); -+ SkDEBUGF("[%s] - %d\n", fallbackSet[i]->familyName.c_str(), static_cast(tpSet.size())); ++ LOGI("[%s] - %d\n", fallbackSet[i]->familyName.c_str(), static_cast(tpSet.size())); + + for (unsigned int j = 0; j < tpSet.size(); j++) { + const FontInfo* font = tpSet[j]->getFontInfo(); + if (font) { + this->dumpFont(*font); + } else { -+ SkDEBUGF("font [%d] is null\n", j); ++ LOGE("font [%d] is null\n", j); + } + } + } @@ -1659,7 +1596,7 @@ index 0000000000..2dfc1348c1 + return logErrInfo(ERROR_CONFIG_MISSING_TAG, "alias"); + } + // "adjust", "variation" - optional -+ const char* tags[] = {"alias", "adjust", "variations", "index"}; ++ const char* tags[] = {"alias", "adjust", "font-variations", "index"}; + std::vector aliasSet; + std::vector adjustSet; + std::vector variationSet; @@ -1824,7 +1761,7 @@ index 0000000000..2dfc1348c1 + bool hasIndex = false; + bool hasVariations = false; + for (unsigned int i = 0; i < members.size(); i++) { -+ if (members[i] == "variations") { ++ if (members[i] == "font-variations") { + hasVariations = true; + } else if (members[i] == "index") { + hasIndex = true; @@ -1842,7 +1779,7 @@ index 0000000000..2dfc1348c1 + SkString lang = SkString(key); + SkString familyName = SkString(root[key].asCString()); + if (hasVariations) { -+ key = "variations"; ++ key = "font-variations"; + if (root[key].isArray()) { + const Json::Value& varArr = root[key]; + std::vector variationSet; @@ -1850,7 +1787,7 @@ index 0000000000..2dfc1348c1 + if (varArr[i].isObject()) { + parseVariation(varArr[i], variationSet); + } else { -+ SkString text = SkString("variations#"); ++ SkString text = SkString("font-variations#"); + text.appendU32(i + 1); + (void) logErrInfo(ERROR_CONFIG_INVALID_VALUE_TYPE, text.c_str(), + Json::objectValue, varArr[i].type()); @@ -1881,7 +1818,7 @@ index 0000000000..2dfc1348c1 + return NO_ERROR; +} + -+/*! To parse an item of 'variations' attribute ++/*! To parse an item of 'font-variations' attribute + * \param root the root node of an item in 'variations' list + * \param[out] variationSet the value of VariationInfo is written to and returned to the caller + * \return NO_ERROR successful @@ -1960,7 +1897,7 @@ index 0000000000..2dfc1348c1 + if (root.size() != keyCount) { + text.appendf("%s#0", key); + errSet.emplace_back(ret, text.c_str()); -+ SkDEBUGF("%s : '%s' size should be 2, but here it's %d\n", errToString(ret), key, root.size()); ++ LOGE("%s : '%s' size should be 2, but here it's %d\n", errToString(ret), key, root.size()); + return ret; + } else if (!root[0].isString()) { + text.appendf("%s#1", key); @@ -2106,7 +2043,7 @@ index 0000000000..2dfc1348c1 + } else { + err = ERROR_FONT_INVALID_STREAM; + } -+ SkDEBUGF("%s : %s\n", errToString(err), fname); ++ LOGE("%s : %s\n", errToString(err), fname); + char* fnameCopy = strdup(fname); + errSet.emplace_back(err, basename(fnameCopy)); + free(fnameCopy); @@ -2358,7 +2295,7 @@ index 0000000000..2dfc1348c1 +{ + errSet.emplace_back(err, key); + if (err != ERROR_CONFIG_INVALID_VALUE_TYPE) { -+ SkDEBUGF("%s : %s\n", errToString(err), key); ++ LOGE("%s : %s\n", errToString(err), key); + } else { + const char* types[] = { + "null", @@ -2373,10 +2310,10 @@ index 0000000000..2dfc1348c1 + int size = sizeof(types) / sizeof(char*); + if ((expected >= 0 && expected < size) && + (actual >= 0 && actual < size)) { -+ SkDEBUGF("%s : '%s' should be '%s', but here it's '%s'\n", ++ LOGE("%s : '%s' should be '%s', but here it's '%s'\n", + errToString(err), key, types[expected], types[actual]); + } else { -+ SkDEBUGF("%s : %s\n", errToString(err), key); ++ LOGE("%s : %s\n", errToString(err), key); + } + } + return err; @@ -2449,10 +2386,10 @@ index 0000000000..2dfc1348c1 +} diff --git a/src/ports/skia_ohos/FontConfig_ohos.h b/src/ports/skia_ohos/FontConfig_ohos.h new file mode 100644 -index 0000000000..edd2c51495 +index 0000000000..d23dc47c44 --- /dev/null +++ b/src/ports/skia_ohos/FontConfig_ohos.h -@@ -0,0 +1,217 @@ +@@ -0,0 +1,234 @@ +// Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. @@ -2473,6 +2410,23 @@ index 0000000000..edd2c51495 +#include "FontInfo_ohos.h" +#include "SkTypeface_ohos.h" + ++#ifdef ENABLE_DEBUG ++ ++#define LOGE(fmt, args...) \ ++ printf("E %s:%d %s - " fmt, basename(__FILE__), __LINE__, __FUNCTION__, ##args) ++#define LOGI(fmt, args...) \ ++ printf("I %s:%d - " fmt, __FUNCTION__, __LINE__, ##args) ++#define LOGW(fmt, args...) \ ++ printf("W %s:%d %s - " fmt, basename(__FILE__), __LINE__, __FUNCTION__, ##args) ++ ++#else ++ ++#define LOGE SkDEBUGF ++#define LOGI SkDEBUGF ++#define LOGW SkDEBUGF ++ ++#endif ++ +struct FontInfo; +struct FallbackInfo; +struct GenericFamily; @@ -2821,9 +2775,15 @@ index 0000000000..0b851ae3fa +}; + +#endif /* FONTINFO_OHOS_H */ +diff --git a/src/ports/skia_ohos/HmSymbolConfig_ohos.cpp b/src/ports/skia_ohos/HmSymbolConfig_ohos.cpp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/src/ports/skia_ohos/HmSymbolConfig_ohos.h b/src/ports/skia_ohos/HmSymbolConfig_ohos.h +new file mode 100644 +index 0000000000..e69de29bb2 diff --git a/src/ports/skia_ohos/SkFontMgr_ohos.cpp b/src/ports/skia_ohos/SkFontMgr_ohos.cpp new file mode 100644 -index 0000000000..a18757d5d5 +index 0000000000..029d105ebc --- /dev/null +++ b/src/ports/skia_ohos/SkFontMgr_ohos.cpp @@ -0,0 +1,437 @@ @@ -2964,7 +2924,7 @@ index 0000000000..a18757d5d5 + } + } + if (item == nullptr) { -+ SkDEBUGF("%s : '%s' must be a fallback key in the config file\n", ++ LOGE("%s : '%s' must be a fallback key in the config file\n", + FontConfig_OHOS::errToString(ERROR_FAMILY_NOT_FOUND), defaultFamily.c_str()); + return nullptr; + } @@ -3182,7 +3142,7 @@ index 0000000000..a18757d5d5 + + std::unique_ptr stream = SkStreamAsset::MakeFromFile(path); + if (stream == nullptr) { -+ SkDEBUGF("%s : %s\n", FontConfig_OHOS::errToString(ERROR_FONT_NOT_EXIST), path); ++ LOGE("%s : %s\n", FontConfig_OHOS::errToString(ERROR_FONT_NOT_EXIST), path); + return nullptr; + } + SkFontArguments args; @@ -3209,7 +3169,7 @@ index 0000000000..a18757d5d5 + if (typeface) { + return sk_sp(typeface); + } -+ SkDEBUGF("%s\n", FontConfig_OHOS::errToString(ERROR_NO_AVAILABLE_FAMILY)); ++ LOGE("%s\n", FontConfig_OHOS::errToString(ERROR_NO_AVAILABLE_FAMILY)); + return nullptr; +} + @@ -3233,14 +3193,14 @@ index 0000000000..a18757d5d5 + if (axisCount == 0) { + if (!fontScanner.scanFont(stream.get(), ttcIndex, &fontInfo.familyName, &fontInfo.style, + &fontInfo.isFixedWidth, nullptr)) { -+ SkDEBUGF("%s\n", FontConfig_OHOS::errToString(ERROR_FONT_INVALID_STREAM)); ++ LOGE("%s\n", FontConfig_OHOS::errToString(ERROR_FONT_INVALID_STREAM)); + return nullptr; + } + } else { + AxisDefinitions axisDef; + if (!fontScanner.scanFont(stream.get(), ttcIndex, &fontInfo.familyName, &fontInfo.style, + &fontInfo.isFixedWidth, &axisDef)) { -+ SkDEBUGF("%s\n", FontConfig_OHOS::errToString(ERROR_FONT_INVALID_STREAM)); ++ LOGE("%s\n", FontConfig_OHOS::errToString(ERROR_FONT_INVALID_STREAM)); + return nullptr; + } + if (axisDef.size() > 0) { @@ -3507,10 +3467,10 @@ index 0000000000..b9fb40cf1e +#endif /* SKFONTSTYLESET_OHOS_H */ diff --git a/src/ports/skia_ohos/SkTypeface_ohos.cpp b/src/ports/skia_ohos/SkTypeface_ohos.cpp new file mode 100644 -index 0000000000..05d3d56d1b +index 0000000000..3141944c32 --- /dev/null +++ b/src/ports/skia_ohos/SkTypeface_ohos.cpp -@@ -0,0 +1,165 @@ +@@ -0,0 +1,139 @@ +// Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. @@ -3521,29 +3481,6 @@ index 0000000000..05d3d56d1b +#include "SkFontHost_FreeType_common.h" +#include "SkTArray.h" + -+#if ENABLE_DEBUG -+/*! To print out the font information -+ * \param font the font object to be printed -+ */ -+void DumpFont(const FontInfo& font) const -+{ -+ SkDEBUGF("name=%s, family=%s, weight=%d, width=%d, slant=%d, index=%d", -+ font.fname.c_str(), font.familyName.c_str(), font.style.weight(), font.style.width(), font.style.slant(), -+ font.index); -+ int count = font.axisSet.axis.size(); -+ if (count > 0) { -+ SkString str; -+ for (unsigned int i = 0; i < count; i++) { -+ str.appendU32(SkFixedFloorToInt(font.axisSet.axis[i])); -+ if (i < count - 1) { -+ str.append(","); -+ } -+ } -+ SkDEBUGF("axis={%s}\n", str.c_str()); -+ } -+} -+#endif -+ +/*! Constructor + * \param familyName the specified family name for the typeface + * \param info the font information for the typeface @@ -3600,9 +3537,6 @@ index 0000000000..05d3d56d1b + if (fontInfo->stream.get() == nullptr) { + return nullptr; + } -+#if ENABLE_DEBUG -+ DumpFont(*fontInfo); -+#endif + return std::make_unique(fontInfo->stream->duplicate(), fontInfo->index, 0, + fontInfo->axisSet.axis.data(), fontInfo->axisSet.axis.size(), nullptr, 0); +} @@ -3718,10 +3652,10 @@ index 0000000000..f80e920de0 +#endif /* SKTYPEFACE_OHOS_H */ diff --git a/src/ports/skia_ohos/config/fontconfig.json b/src/ports/skia_ohos/config/fontconfig.json new file mode 100644 -index 0000000000..ec225a188e +index 0000000000..2c5458bc6b --- /dev/null +++ b/src/ports/skia_ohos/config/fontconfig.json -@@ -0,0 +1,76 @@ +@@ -0,0 +1,1373 @@ +{ + "fontdir": ["/system/fonts/"], + "generic": [ @@ -3757,6 +3691,26 @@ index 0000000000..ec225a188e + { + "weight": 200, "to": 900 + } ++ ], ++ "font-variations": [ ++ { ++ "weight": 100, "wght": 100 ++ }, ++ { ++ "weight": 300, "wght": 247 ++ }, ++ { ++ "weight": 400, "wght": 400 ++ }, ++ { ++ "weight": 500, "wght": 500 ++ }, ++ { ++ "weight": 700, "wght": 706 ++ }, ++ { ++ "weight": 900, "wght": 844 ++ } + ] + }, + { @@ -3765,6 +3719,26 @@ index 0000000000..ec225a188e + { + "HarmonyOS-Sans-Condensed": 0 + } ++ ], ++ "font-variations": [ ++ { ++ "weight": 100, "wght": 100 ++ }, ++ { ++ "weight": 300, "wght": 247 ++ }, ++ { ++ "weight": 400, "wght": 400 ++ }, ++ { ++ "weight": 500, "wght": 500 ++ }, ++ { ++ "weight": 700, "wght": 706 ++ }, ++ { ++ "weight": 900, "wght": 844 ++ } + ] + }, + { @@ -3774,27 +3748,1284 @@ index 0000000000..ec225a188e + "HarmonyOS-Sans-Digit": 0 + } + ] ++ }, ++ { ++ "family": "Noto Serif", ++ "alias": [ ++ { ++ "serif": 0 ++ } ++ ] ++ }, ++ { ++ "family": "Noto Sans Mono", ++ "alias": [ ++ { ++ "monospace": 400 ++ } ++ ] + } + ], + "fallback": [ + { + "": [ + { -+ "zh-Hans": "HarmonyOS Sans SC" ++ "und-Zsye": "HMOS Color Emoji" + }, + { -+ "zh-Hant": "HarmonyOS Sans TC" ++ "": "Noto Sans" + }, + { ++ "font-variations": [ ++ { ++ "weight": 100, "wght": 100 ++ }, ++ { ++ "weight": 300, "wght": 247 ++ }, ++ { ++ "weight": 400, "wght": 400 ++ }, ++ { ++ "weight": 500, "wght": 500 ++ }, ++ { ++ "weight": 700, "wght": 706 ++ }, ++ { ++ "weight": 900, "wght": 844 ++ } ++ ], + "und-Arab": "HarmonyOS Sans Naskh Arabic UI" + }, + { -+ "ja": "Noto Sans JP" ++ "und-Ethi": "Noto Sans Ethiopic" + }, + { -+ "ko": "Noto Sans KR" -+ } -+ ] ++ "und-Hebr": "Noto Sans Hebrew" ++ }, ++ { ++ "und-Thai": "Noto Sans Thai" ++ }, ++ { ++ "und-Armn": "Noto Sans Armenian" ++ }, ++ { ++ "und-Geor,und-Geok": "Noto Sans Georgian" ++ }, ++ { ++ "und-Deva": "Noto Sans Devanagari" ++ }, ++ { ++ "und-Gujr": "Noto Sans Gujarati" ++ }, ++ { ++ "und-Guru": "Noto Sans Gurmukhi" ++ }, ++ { ++ "und-Taml": "Noto Sans Tamil" ++ }, ++ { ++ "und-Mlym": "Noto Sans Malayalam" ++ }, ++ { ++ "und-Beng": "Noto Sans Bengali" ++ }, ++ { ++ "und-Telu": "Noto Sans Telugu" ++ }, ++ { ++ "und-Knda": "Noto Sans Kannada" ++ }, ++ { ++ "und-Orya": "Noto Sans Oriya" ++ }, ++ { ++ "und-Sinh": "Noto Sans Sinhala" ++ }, ++ { ++ "und-Khmr": "Noto Sans Khmer" ++ }, ++ { ++ "und-Laoo": "Noto Sans Lao" ++ }, ++ { ++ "und-Mymr": "Noto Sans Myanmar" ++ }, ++ { ++ "und-Thaa": "Noto Sans Thaana" ++ }, ++ { ++ "und-Cham": "Noto Sans Cham" ++ }, ++ { ++ "und-Ahom": "Noto Serif Ahom" ++ }, ++ { ++ "und-Adlm": "Noto Sans Adlam" ++ }, ++ { ++ "und-Avst": "Noto Sans Avestan" ++ }, ++ { ++ "und-Bali": "Noto Sans Balinese" ++ }, ++ { ++ "und-Bamu": "Noto Sans Bamum" ++ }, ++ { ++ "und-Batk": "Noto Sans Batak" ++ }, ++ { ++ "und-Brah": "Noto Sans Brahmi" ++ }, ++ { ++ "und-Bugi": "Noto Sans Buginese" ++ }, ++ { ++ "und-Buhd": "Noto Sans Buhid" ++ }, ++ { ++ "und-Cans": "Noto Sans Canadian Aboriginal" ++ }, ++ { ++ "und-Cari": "Noto Sans Carian" ++ }, ++ { ++ "und-Cakm": "Noto Sans Chakma" ++ }, ++ { ++ "und-Cher": "Noto Sans Cherokee" ++ }, ++ { ++ "und-Copt": "Noto Sans Coptic" ++ }, ++ { ++ "und-Xsux": "Noto Sans Cuneiform" ++ }, ++ { ++ "und-Cprt": "Noto Sans Cypriot" ++ }, ++ { ++ "und-Dsrt": "Noto Sans Deseret" ++ }, ++ { ++ "und-Egyp": "Noto Sans Egyptian Hieroglyphs" ++ }, ++ { ++ "und-Elba": "Noto Sans Elbasan" ++ }, ++ { ++ "und-Glag": "Noto Sans Glagolitic" ++ }, ++ { ++ "und-Goth": "Noto Sans Gothic" ++ }, ++ { ++ "und-Hano": "Noto Sans Hanunoo" ++ }, ++ { ++ "und-Armi": "Noto Sans Imperial Aramaic" ++ }, ++ { ++ "und-Phli": "Noto Sans Inscriptional Pahlavi" ++ }, ++ { ++ "und-Prti": "Noto Sans Inscriptional Parthian" ++ }, ++ { ++ "und-Java": "Noto Sans Javanese" ++ }, ++ { ++ "und-Kthi": "Noto Sans Kaithi" ++ }, ++ { ++ "und-Kali": "Noto Sans Kayah Li" ++ }, ++ { ++ "und-Khar": "Noto Sans Kharoshthi" ++ }, ++ { ++ "und-Lepc": "Noto Sans Lepcha" ++ }, ++ { ++ "und-Limb": "Noto Sans Limbu" ++ }, ++ { ++ "und-Linb": "Noto Sans Linear B" ++ }, ++ { ++ "und-Lisu": "Noto Sans Lisu" ++ }, ++ { ++ "und-Lyci": "Noto Sans Lycian" ++ }, ++ { ++ "und-Lydi": "Noto Sans Lydian" ++ }, ++ { ++ "und-Mand": "Noto Sans Mandaic" ++ }, ++ { ++ "und-Mtei": "Noto Sans Meetei Mayek" ++ }, ++ { ++ "und-Talu": "Noto Sans New Tai Lue" ++ }, ++ { ++ "und-Nkoo": "Noto Sans NKo" ++ }, ++ { ++ "und-Ogam": "Noto Sans Ogham" ++ }, ++ { ++ "und-Olck": "Noto Sans Ol Chiki" ++ }, ++ { ++ "und-Ital": "Noto Sans Old Italic" ++ }, ++ { ++ "und-Xpeo": "Noto Sans Old Persian" ++ }, ++ { ++ "und-Sarb": "Noto Sans Old South Arabian" ++ }, ++ { ++ "und-Orkh": "Noto Sans Old Turkic" ++ }, ++ { ++ "und-Osge": "Noto Sans Osage" ++ }, ++ { ++ "und-Osma": "Noto Sans Osmanya" ++ }, ++ { ++ "und-Phnx": "Noto Sans Phoenician" ++ }, ++ { ++ "und-Rjng": "Noto Sans Rejang" ++ }, ++ { ++ "und-Runr": "Noto Sans Runic" ++ }, ++ { ++ "und-Samr": "Noto Sans Samaritan" ++ }, ++ { ++ "und-Saur": "Noto Sans Saurashtra" ++ }, ++ { ++ "und-Shaw": "Noto Sans Shavian" ++ }, ++ { ++ "und-Sund": "Noto Sans Sundanese" ++ }, ++ { ++ "und-Sylo": "Noto Sans Syloti Nagri" ++ }, ++ { ++ "und-Syrn": "Noto Sans Syriac Eastern" ++ }, ++ { ++ "und-Syrj": "Noto Sans Syriac Western" ++ }, ++ { ++ "und-Tglg": "Noto Sans Tagalog" ++ }, ++ { ++ "und-Tagb": "Noto Sans Tagbanwa" ++ }, ++ { ++ "und-Lana": "Noto Sans Tai Tham" ++ }, ++ { ++ "und-Tavt": "Noto Sans Tai Viet" ++ }, ++ { ++ "und-Tibt": "Noto Serif Tibetan" ++ }, ++ { ++ "und-Tfng": "Noto Sans Tifinagh" ++ }, ++ { ++ "und-Ugar": "Noto Sans Ugaritic" ++ }, ++ { ++ "und-Vaii": "Noto Sans Vai" ++ }, ++ { ++ "font-variations": [ ++ { ++ "weight": 100, "wght": 100 ++ }, ++ { ++ "weight": 300, "wght": 247 ++ }, ++ { ++ "weight": 400, "wght": 400 ++ }, ++ { ++ "weight": 500, "wght": 500 ++ }, ++ { ++ "weight": 600, "wght": 603 ++ }, ++ { ++ "weight": 700, "wght": 706 ++ }, ++ { ++ "weight": 900, "wght": 844 ++ } ++ ], ++ "zh-Hans": "HarmonyOS Sans SC" ++ }, ++ { ++ "font-variations": [ ++ { ++ "weight": 100, "wght": 100 ++ }, ++ { ++ "weight": 300, "wght": 247 ++ }, ++ { ++ "weight": 400, "wght": 400 ++ }, ++ { ++ "weight": 500, "wght": 500 ++ }, ++ { ++ "weight": 700, "wght": 706 ++ }, ++ { ++ "weight": 900, "wght": 844 ++ } ++ ], ++ "zh-Hant": "HarmonyOS Sans TC" ++ }, ++ { ++ "ja": "Noto Sans CJK JP" ++ }, ++ { ++ "ko": "Noto Sans CJK JP" ++ }, ++ { ++ "und-Zsye": "HMOS Color Emoji Flags" ++ }, ++ { ++ "und-Zsym": "Noto Sans Symbols" ++ }, ++ { ++ "und-Zsym": "Noto Sans Symbols 2" ++ }, ++ { ++ "und-Tale": "Noto Sans Tai Le" ++ }, ++ { ++ "und-Yiii": "Noto Sans Yi" ++ }, ++ { ++ "und-Mong": "Noto Sans Mongolian" ++ }, ++ { ++ "und-Phag": "Noto Sans Phags-Pa" ++ }, ++ { ++ "und-Hluw": "Noto Sans Anatolian Hieroglyphs" ++ }, ++ { ++ "und-Bass": "Noto Sans Bassa Vah" ++ }, ++ { ++ "und-Bhks": "Noto Sans Bhaiksuki" ++ }, ++ { ++ "und-Hatr": "Noto Sans Hatran" ++ }, ++ { ++ "und-Lina": "Noto Sans Linear A" ++ }, ++ { ++ "und-Mani": "Noto Sans Manichaean" ++ }, ++ { ++ "und-Marc": "Noto Sans Marchen" ++ }, ++ { ++ "und-Merc": "Noto Sans Meroitic" ++ }, ++ { ++ "und-Plrd": "Noto Sans Miao" ++ }, ++ { ++ "und-Mroo": "Noto Sans Mro" ++ }, ++ { ++ "und-Mult": "Noto Sans Multani" ++ }, ++ { ++ "und-Nbat": "Noto Sans Nabataean" ++ }, ++ { ++ "und-Newa": "Noto Sans Newa" ++ }, ++ { ++ "und-Narb": "Noto Sans Old North Arabian" ++ }, ++ { ++ "und-Perm": "Noto Sans Old Permic" ++ }, ++ { ++ "und-Hmng": "Noto Sans Pahawh Hmong" ++ }, ++ { ++ "und-Palm": "Noto Sans Palmyrene" ++ }, ++ { ++ "und-Pauc": "Noto Sans Pau Cin Hau" ++ }, ++ { ++ "und-Shrd": "Noto Sans Sharada" ++ }, ++ { ++ "und-Sora": "Noto Sans Sora Sompeng" ++ }, ++ { ++ "und-Gong": "Noto Sans Gunjala Gondi" ++ }, ++ { ++ "und-Rohg": "Noto Sans Hanifi Rohingya" ++ }, ++ { ++ "und-Khoj": "Noto Sans Khojki" ++ }, ++ { ++ "und-Gonm": "Noto Sans Masaram Gondi" ++ }, ++ { ++ "und-Wcho": "Noto Sans Wancho" ++ }, ++ { ++ "und-Wara": "Noto Sans Warang Citi" ++ }, ++ { ++ "und-Gran": "Noto Sans Grantha" ++ }, ++ { ++ "und-Modi": "Noto Sans Modi" ++ }, ++ { ++ "und-Dogr": "Noto Serif Dogra" ++ }, ++ { ++ "und-Medf": "Noto Sans Medefaidrin" ++ }, ++ { ++ "und-Soyo": "Noto Sans Soyombo" ++ }, ++ { ++ "und-Takr": "Noto Sans Takri" ++ }, ++ { ++ "und-Yezi": "Noto Serif Yezidi" ++ }, ++ { ++ "und-Zsym": "HM Symbol" ++ }, ++ { ++ "und-Math": "Noto Sans Math" ++ } ++ ] ++ } ++ ], ++ "font_file_map" : [ ++ { ++ "DejaVuMathTeXGyre-Regular": "DejaVuMathTeXGyre.ttf" ++ }, ++ { ++ "FTSymbol": "FTSymbol.ttf" ++ }, ++ { ++ "FTToken": "FTToken.ttf" ++ }, ++ { ++ "FTToken2": "FTToken2.ttf" ++ }, ++ { ++ "FTToken3": "FTToken3.ttf" ++ }, ++ { ++ "FTTokens": "FTTokens.ttf" ++ }, ++ { ++ "方正仿宋-简": "FZFangS-SC.ttf" ++ }, ++ { ++ "FZFangS-SC": "FZFangS-SC.ttf" ++ }, ++ { ++ "方正仿宋-繁": "FZFangS-TC.ttf" ++ }, ++ { ++ "FZFangS-TC": "FZFangS-TC.ttf" ++ }, ++ { ++ "FZHeiT-SC Bold": "FZHeiT-SC-Bold.ttf" ++ }, ++ { ++ "FZHeiT-SC Light": "FZHeiT-SC-Light.ttf" ++ }, ++ { ++ "FZHeiT-SC": "FZHeiT-SC-Regular.ttf" ++ }, ++ { ++ "FZHeiT-TC Bold": "FZHeiT-TC-Bold.ttf" ++ }, ++ { ++ "方正黑體-繁 Bold": "FZHeiT-TC-Bold.ttf" ++ }, ++ { ++ "FZHeiT-TC Light": "FZHeiT-TC-Light.ttf" ++ }, ++ { ++ "方正黑體-繁 Light": "FZHeiT-TC-Light.ttf" ++ }, ++ { ++ "FZHeiT-TC": "FZHeiT-TC-Regular.ttf" ++ }, ++ { ++ "方正黑體-繁": "FZHeiT-TC-Regular.ttf" ++ }, ++ { ++ "方正楷体-简": "FZKaiT-SC.ttf" ++ }, ++ { ++ "FZKaiT-SC": "FZKaiT-SC.ttf" ++ }, ++ { ++ "方正楷體-繁": "FZKaiT-TC.ttf" ++ }, ++ { ++ "FZKaiT-TC": "FZKaiT-TC.ttf" ++ }, ++ { ++ "方正隶体-简": "FZLiT-SC.ttf" ++ }, ++ { ++ "FZLiT-SC": "FZLiT-SC.ttf" ++ }, ++ { ++ "方正隸變-繁": "FZLiB-TC.ttf" ++ }, ++ { ++ "FZLiB-TC": "FZLiB-TC.ttf" ++ }, ++ { ++ "方正隶书-简": "FZLiS-SC.ttf" ++ }, ++ { ++ "FZLiS-SC": "FZLiS-SC.ttf" ++ }, ++ { ++ "方正隸書-繁": "FZLiS-TC.ttf" ++ }, ++ { ++ "FZLiS-TC": "FZLiS-TC.ttf" ++ }, ++ { ++ "方正喵呜-简": "FZMiaoW-SC.ttf" ++ }, ++ { ++ "FZMiaoW-SC": "FZMiaoW-SC.ttf" ++ }, ++ { ++ "方正喵體-繁": "FZMiaoT-TC.ttf" ++ }, ++ { ++ "FZMiaoT-TC": "FZMiaoT-TC.ttf" ++ }, ++ { ++ "方正手书-简": "FZShouS-SC.ttf" ++ }, ++ { ++ "FZShouS-SC": "FZShouS-SC.ttf" ++ }, ++ { ++ "方正手書-繁": "FZShouS-TC.ttf" ++ }, ++ { ++ "FZShouS-TC": "FZShouS-TC.ttf" ++ }, ++ { ++ "方正书宋-简": "FZShuS-SC.ttf" ++ }, ++ { ++ "FZShuS-SC": "FZShuS-SC.ttf" ++ }, ++ { ++ "方正書宋-繁": "FZShuS-TC.ttf" ++ }, ++ { ++ "FZShuS-TC": "FZShuS-TC.ttf" ++ }, ++ { ++ "方正小标宋-简": "FZXiaoBS-SC.ttf" ++ }, ++ { ++ "FZXiaoBS-SC": "FZXiaoBS-SC.ttf" ++ }, ++ { ++ "方正小標宋-繁": "FZXiaoBS-TC.ttf" ++ }, ++ { ++ "FZXiaoBS-TC": "FZXiaoBS-TC.ttf" ++ }, ++ { ++ "方正行楷-简": "FZXingK-SC.ttf" ++ }, ++ { ++ "FZXingK-SC": "FZXingK-SC.ttf" ++ }, ++ { ++ "方正行楷-繁": "FZXingK-TC.ttf" ++ }, ++ { ++ "FZXingK-TC": "FZXingK-TC.ttf" ++ }, ++ { ++ "FZYuanT-SC Bold": "FZYuanT-SC-Bold.ttf" ++ }, ++ { ++ "FZYuanT-SC Light": "FZYuanT-SC-Light.ttf" ++ }, ++ { ++ "FZYuanT-SC": "FZYuanT-SC-Regular.ttf" ++ }, ++ { ++ "FZYuanT-TC Bold": "FZYuanT-TC-Bold.ttf" ++ }, ++ { ++ "方正圓體-繁 Bold": "FZYuanT-TC-Bold.ttf" ++ }, ++ { ++ "FZYuanT-TC Light": "FZYuanT-TC-Light.ttf" ++ }, ++ { ++ "方正圓體-繁 Light": "FZYuanT-TC-Light.ttf" ++ }, ++ { ++ "FZYuanT-TC": "FZYuanT-TC-Regular.ttf" ++ }, ++ { ++ "方正圓體-繁": "FZYuanT-TC-Regular.ttf" ++ }, ++ { ++ "HMOS Color Emoji": "HMOSColorEmojiCompat.ttf" ++ }, ++ { ++ "HMOS Color Emoji Flags": "HMOSColorEmojiFlags.ttf" ++ }, ++ { ++ "HM Symbol Regular": "HMSymbolVF.ttf" ++ }, ++ { ++ "HarmonyOS Sans": "HarmonyOS_Sans.ttf" ++ }, ++ { ++ "HarmonyOS Sans Condensed": "HarmonyOS_Sans_Condensed.ttf" ++ }, ++ { ++ "HarmonyOS Sans Condensed Italic": "HarmonyOS_Sans_Condensed_Italic.ttf" ++ }, ++ { ++ "HarmonyOS Sans Digit": "HarmonyOS_Sans_Digit.ttf" ++ }, ++ { ++ "HarmonyOS Sans Digit": "HarmonyOS_Sans_Digit_Medium.ttf" ++ }, ++ { ++ "HarmonyOS Sans Italic": "HarmonyOS_Sans_Italic.ttf" ++ }, ++ { ++ "HarmonyOS Sans Naskh Arabic": "HarmonyOS_Sans_Naskh_Arabic.ttf" ++ }, ++ { ++ "HarmonyOS Sans Naskh Arabic UI": "HarmonyOS_Sans_Naskh_Arabic_UI.ttf" ++ }, ++ { ++ "HarmonyOS Sans SC": "HarmonyOS_Sans_SC.ttf" ++ }, ++ { ++ "HarmonyOS Sans TC": "HarmonyOS_Sans_TC.ttf" ++ }, ++ { ++ "Noto Sans Adlam Regular": "NotoSansAdlam[wght].ttf" ++ }, ++ { ++ "Noto Sans Anatolian Hieroglyphs Regular": "NotoSansAnatolianHieroglyphs-Regular.ttf" ++ }, ++ { ++ "Noto Sans Armenian Regular": "NotoSansArmenian[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Avestan Regular": "NotoSansAvestan-Regular.ttf" ++ }, ++ { ++ "Noto Sans Balinese Regular": "NotoSansBalinese[wght].ttf" ++ }, ++ { ++ "Noto Sans Bamum Regular": "NotoSansBamum[wght].ttf" ++ }, ++ { ++ "Noto Sans Bassa Vah Regular": "NotoSansBassaVah[wght].ttf" ++ }, ++ { ++ "Noto Sans Batak Regular": "NotoSansBatak-Regular.ttf" ++ }, ++ { ++ "Noto Sans Bengali UI Bold": "NotoSansBengaliUI-Bold.ttf" ++ }, ++ { ++ "Noto Sans Bengali UI Medium": "NotoSansBengaliUI-Medium.ttf" ++ }, ++ { ++ "Noto Sans Bengali UI Regular": "NotoSansBengaliUI-Regular.ttf" ++ }, ++ { ++ "Noto Sans Bengali UI SemiBold": "NotoSansBengaliUI-SemiBold.ttf" ++ }, ++ { ++ "Noto Sans Bengali Regular": "NotoSansBengali[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Bhaiksuki Regular": "NotoSansBhaiksuki-Regular.ttf" ++ }, ++ { ++ "Noto Sans Brahmi Regular": "NotoSansBrahmi-Regular.ttf" ++ }, ++ { ++ "Noto Sans Buginese Regular": "NotoSansBuginese-Regular.ttf" ++ }, ++ { ++ "Noto Sans Buhid Regular": "NotoSansBuhid-Regular.ttf" ++ }, ++ { ++ "Noto Sans CJK JP": "NotoSansCJK-Regular.ttc" ++ }, ++ { ++ "Noto Sans Canadian Aboriginal Regular": "NotoSansCanadianAboriginal[wght].ttf" ++ }, ++ { ++ "Noto Sans Carian Regular": "NotoSansCarian-Regular.ttf" ++ }, ++ { ++ "Noto Sans Chakma Regular": "NotoSansChakma-Regular.ttf" ++ }, ++ { ++ "Noto Sans Cham Regular": "NotoSansCham[wght].ttf" ++ }, ++ { ++ "Noto Sans Cherokee Regular": "NotoSansCherokee[wght].ttf" ++ }, ++ { ++ "Noto Sans Coptic Regular": "NotoSansCoptic-Regular.ttf" ++ }, ++ { ++ "Noto Sans Cuneiform Regular": "NotoSansCuneiform-Regular.ttf" ++ }, ++ { ++ "Noto Sans Cypriot Regular": "NotoSansCypriot-Regular.ttf" ++ }, ++ { ++ "Noto Sans Deseret Regular": "NotoSansDeseret-Regular.ttf" ++ }, ++ { ++ "Noto Sans Devanagari UI Bold": "NotoSansDevanagariUI-Bold.ttf" ++ }, ++ { ++ "Noto Sans Devanagari UI Medium": "NotoSansDevanagariUI-Medium.ttf" ++ }, ++ { ++ "Noto Sans Devanagari UI Regular": "NotoSansDevanagariUI-Regular.ttf" ++ }, ++ { ++ "Noto Sans Devanagari UI SemiBold": "NotoSansDevanagariUI-SemiBold.ttf" ++ }, ++ { ++ "Noto Sans Devanagari Regular": "NotoSansDevanagari[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Egyptian Hieroglyphs Regular": "NotoSansEgyptianHieroglyphs-Regular.ttf" ++ }, ++ { ++ "Noto Sans Elbasan Regular": "NotoSansElbasan-Regular.ttf" ++ }, ++ { ++ "Noto Sans Ethiopic Regular": "NotoSansEthiopic[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Georgian Regular": "NotoSansGeorgian[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Glagolitic Regular": "NotoSansGlagolitic-Regular.ttf" ++ }, ++ { ++ "Noto Sans Gothic Regular": "NotoSansGothic-Regular.ttf" ++ }, ++ { ++ "Noto Sans Grantha Regular": "NotoSansGrantha-Regular.ttf" ++ }, ++ { ++ "Noto Sans Gujarati UI Bold": "NotoSansGujaratiUI-Bold.ttf" ++ }, ++ { ++ "Noto Sans Gujarati UI Regular": "NotoSansGujaratiUI-Regular.ttf" ++ }, ++ { ++ "Noto Sans Gujarati Regular": "NotoSansGujarati[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Gunjala Gondi Regular": "NotoSansGunjalaGondi[wght].ttf" ++ }, ++ { ++ "Noto Sans Gurmukhi UI Bold": "NotoSansGurmukhiUI-Bold.ttf" ++ }, ++ { ++ "Noto Sans Gurmukhi UI Medium": "NotoSansGurmukhiUI-Medium.ttf" ++ }, ++ { ++ "Noto Sans Gurmukhi UI Regular": "NotoSansGurmukhiUI-Regular.ttf" ++ }, ++ { ++ "Noto Sans Gurmukhi UI SemiBold": "NotoSansGurmukhiUI-SemiBold.ttf" ++ }, ++ { ++ "Noto Sans Gurmukhi Regular": "NotoSansGurmukhi[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Hanifi Rohingya Regular": "NotoSansHanifiRohingya[wght].ttf" ++ }, ++ { ++ "Noto Sans Hanunoo Regular": "NotoSansHanunoo-Regular.ttf" ++ }, ++ { ++ "Noto Sans Hatran Regular": "NotoSansHatran-Regular.ttf" ++ }, ++ { ++ "Noto Sans Hebrew Regular": "NotoSansHebrew[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Imperial Aramaic Regular": "NotoSansImperialAramaic-Regular.ttf" ++ }, ++ { ++ "Noto Sans Inscriptional Pahlavi Regular": "NotoSansInscriptionalPahlavi-Regular.ttf" ++ }, ++ { ++ "Noto Sans Inscriptional Parthian Regular": "NotoSansInscriptionalParthian-Regular.ttf" ++ }, ++ { ++ "Noto Sans Javanese Regular": "NotoSansJavanese[wght].ttf" ++ }, ++ { ++ "Noto Sans Kaithi Regular": "NotoSansKaithi-Regular.ttf" ++ }, ++ { ++ "Noto Sans Kannada UI Bold": "NotoSansKannadaUI-Bold.ttf" ++ }, ++ { ++ "Noto Sans Kannada UI Medium": "NotoSansKannadaUI-Medium.ttf" ++ }, ++ { ++ "Noto Sans Kannada UI Regular": "NotoSansKannadaUI-Regular.ttf" ++ }, ++ { ++ "Noto Sans Kannada UI SemiBold": "NotoSansKannadaUI-SemiBold.ttf" ++ }, ++ { ++ "Noto Sans Kannada Regular": "NotoSansKannada[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Kayah Li Regular": "NotoSansKayahLi[wght].ttf" ++ }, ++ { ++ "Noto Sans Kharoshthi Regular": "NotoSansKharoshthi-Regular.ttf" ++ }, ++ { ++ "Noto Sans Khmer Regular": "NotoSansKhmer[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Khojki Regular": "NotoSansKhojki-Regular.ttf" ++ }, ++ { ++ "Noto Sans Lao Regular": "NotoSansLao[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Lepcha Regular": "NotoSansLepcha-Regular.ttf" ++ }, ++ { ++ "Noto Sans Limbu Regular": "NotoSansLimbu-Regular.ttf" ++ }, ++ { ++ "Noto Sans Linear A Regular": "NotoSansLinearA-Regular.ttf" ++ }, ++ { ++ "Noto Sans Linear B Regular": "NotoSansLinearB-Regular.ttf" ++ }, ++ { ++ "Noto Sans Lisu Regular": "NotoSansLisu[wght].ttf" ++ }, ++ { ++ "Noto Sans Lycian Regular": "NotoSansLycian-Regular.ttf" ++ }, ++ { ++ "Noto Sans Lydian Regular": "NotoSansLydian-Regular.ttf" ++ }, ++ { ++ "Noto Sans Malayalam UI Bold": "NotoSansMalayalamUI-Bold.ttf" ++ }, ++ { ++ "Noto Sans Malayalam UI Medium": "NotoSansMalayalamUI-Medium.ttf" ++ }, ++ { ++ "Noto Sans Malayalam UI Regular": "NotoSansMalayalamUI-Regular.ttf" ++ }, ++ { ++ "Noto Sans Malayalam UI SemiBold": "NotoSansMalayalamUI-SemiBold.ttf" ++ }, ++ { ++ "Noto Sans Malayalam Regular": "NotoSansMalayalam[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Mandaic Regular": "NotoSansMandaic-Regular.ttf" ++ }, ++ { ++ "Noto Sans Manichaean Regular": "NotoSansManichaean-Regular.ttf" ++ }, ++ { ++ "Noto Sans Marchen Regular": "NotoSansMarchen-Regular.ttf" ++ }, ++ { ++ "Noto Sans Masaram Gondi Regular": "NotoSansMasaramGondi-Regular.ttf" ++ }, ++ { ++ "Noto Sans Medefaidrin Regular": "NotoSansMedefaidrin[wght].ttf" ++ }, ++ { ++ "Noto Sans Meetei Mayek Regular": "NotoSansMeeteiMayek[wght].ttf" ++ }, ++ { ++ "Noto Sans Meroitic Regular": "NotoSansMeroitic-Regular.ttf" ++ }, ++ { ++ "Noto Sans Miao Regular": "NotoSansMiao-Regular.ttf" ++ }, ++ { ++ "Noto Sans Modi Regular": "NotoSansModi-Regular.ttf" ++ }, ++ { ++ "Noto Sans Mongolian Regular": "NotoSansMongolian-Regular.ttf" ++ }, ++ { ++ "Noto Sans Mono Regular": "NotoSansMono[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Mro Regular": "NotoSansMro-Regular.ttf" ++ }, ++ { ++ "Noto Sans Multani Regular": "NotoSansMultani-Regular.ttf" ++ }, ++ { ++ "Noto Sans Myanmar Regular": "NotoSansMyanmar[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans NKo Regular": "NotoSansNKo-Regular.ttf" ++ }, ++ { ++ "Noto Sans Nabataean Regular": "NotoSansNabataean-Regular.ttf" ++ }, ++ { ++ "Noto Sans New Tai Lue Regular": "NotoSansNewTaiLue[wght].ttf" ++ }, ++ { ++ "Noto Sans Newa Regular": "NotoSansNewa-Regular.ttf" ++ }, ++ { ++ "Noto Sans Ogham Regular": "NotoSansOgham-Regular.ttf" ++ }, ++ { ++ "Noto Sans Ol Chiki Regular": "NotoSansOlChiki[wght].ttf" ++ }, ++ { ++ "Noto Sans Old Italic Regular": "NotoSansOldItalic-Regular.ttf" ++ }, ++ { ++ "Noto Sans Old North Arabian Regular": "NotoSansOldNorthArabian-Regular.ttf" ++ }, ++ { ++ "Noto Sans Old Permic Regular": "NotoSansOldPermic-Regular.ttf" ++ }, ++ { ++ "Noto Sans Old Persian Regular": "NotoSansOldPersian-Regular.ttf" ++ }, ++ { ++ "Noto Sans Old South Arabian Regular": "NotoSansOldSouthArabian-Regular.ttf" ++ }, ++ { ++ "Noto Sans Old Turkic Regular": "NotoSansOldTurkic-Regular.ttf" ++ }, ++ { ++ "Noto Sans Oriya Regular": "NotoSansOriya[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Osage Regular": "NotoSansOsage-Regular.ttf" ++ }, ++ { ++ "Noto Sans Osmanya Regular": "NotoSansOsmanya-Regular.ttf" ++ }, ++ { ++ "Noto Sans Pahawh Hmong Regular": "NotoSansPahawhHmong-Regular.ttf" ++ }, ++ { ++ "Noto Sans Palmyrene Regular": "NotoSansPalmyrene-Regular.ttf" ++ }, ++ { ++ "Noto Sans Pau Cin Hau Regular": "NotoSansPauCinHau-Regular.ttf" ++ }, ++ { ++ "Noto Sans Phags-Pa Regular": "NotoSansPhags-Pa-Regular.ttf" ++ }, ++ { ++ "Noto Sans Phoenician Regular": "NotoSansPhoenician-Regular.ttf" ++ }, ++ { ++ "Noto Sans Rejang Regular": "NotoSansRejang-Regular.ttf" ++ }, ++ { ++ "Noto Sans Runic Regular": "NotoSansRunic-Regular.ttf" ++ }, ++ { ++ "Noto Sans Samaritan Regular": "NotoSansSamaritan-Regular.ttf" ++ }, ++ { ++ "Noto Sans Saurashtra Regular": "NotoSansSaurashtra-Regular.ttf" ++ }, ++ { ++ "Noto Sans Sharada Regular": "NotoSansSharada-Regular.ttf" ++ }, ++ { ++ "Noto Sans Shavian Regular": "NotoSansShavian-Regular.ttf" ++ }, ++ { ++ "Noto Sans Sinhala UI Bold": "NotoSansSinhalaUI-Bold.ttf" ++ }, ++ { ++ "Noto Sans Sinhala UI Medium": "NotoSansSinhalaUI-Medium.ttf" ++ }, ++ { ++ "Noto Sans Sinhala UI Regular": "NotoSansSinhalaUI-Regular.ttf" ++ }, ++ { ++ "Noto Sans Sinhala UI SemiBold": "NotoSansSinhalaUI-SemiBold.ttf" ++ }, ++ { ++ "Noto Sans Sinhala Regular": "NotoSansSinhala[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Sora Sompeng Regular": "NotoSansSoraSompeng[wght].ttf" ++ }, ++ { ++ "Noto Sans Soyombo Regular": "NotoSansSoyombo-Regular.ttf" ++ }, ++ { ++ "Noto Sans Sundanese Regular": "NotoSansSundanese[wght].ttf" ++ }, ++ { ++ "Noto Sans Syloti Nagri Regular": "NotoSansSylotiNagri-Regular.ttf" ++ }, ++ { ++ "Noto Sans Symbols Regular": "NotoSansSymbols-Regular.ttf" ++ }, ++ { ++ "Noto Sans Symbols 2 Regular": "NotoSansSymbols2-Regular.ttf" ++ }, ++ { ++ "Noto Sans Syriac Eastern Regular": "NotoSansSyriacEastern[wght].ttf" ++ }, ++ { ++ "Noto Sans Syriac Western Regular": "NotoSansSyriacWestern[wght].ttf" ++ }, ++ { ++ "Noto Sans Tagalog Regular": "NotoSansTagalog-Regular.ttf" ++ }, ++ { ++ "Noto Sans Tagbanwa Regular": "NotoSansTagbanwa-Regular.ttf" ++ }, ++ { ++ "Noto Sans Tai Le Regular": "NotoSansTaiLe-Regular.ttf" ++ }, ++ { ++ "Noto Sans Tai Tham Regular": "NotoSansTaiTham[wght].ttf" ++ }, ++ { ++ "Noto Sans Tai Viet Regular": "NotoSansTaiViet-Regular.ttf" ++ }, ++ { ++ "Noto Sans Takri Regular": "NotoSansTakri-Regular.ttf" ++ }, ++ { ++ "Noto Sans Tamil UI Bold": "NotoSansTamilUI-Bold.ttf" ++ }, ++ { ++ "Noto Sans Tamil UI Medium": "NotoSansTamilUI-Medium.ttf" ++ }, ++ { ++ "Noto Sans Tamil UI Regular": "NotoSansTamilUI-Regular.ttf" ++ }, ++ { ++ "Noto Sans Tamil UI SemiBold": "NotoSansTamilUI-SemiBold.ttf" ++ }, ++ { ++ "Noto Sans Tamil Regular": "NotoSansTamil[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Telugu UI Bold": "NotoSansTeluguUI-Bold.ttf" ++ }, ++ { ++ "Noto Sans Telugu UI Medium": "NotoSansTeluguUI-Medium.ttf" ++ }, ++ { ++ "Noto Sans Telugu UI Regular": "NotoSansTeluguUI-Regular.ttf" ++ }, ++ { ++ "Noto Sans Telugu UI SemiBold": "NotoSansTeluguUI-SemiBold.ttf" ++ }, ++ { ++ "Noto Sans Telugu Regular": "NotoSansTelugu[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Thaana Regular": "NotoSansThaana[wght].ttf" ++ }, ++ { ++ "Noto Sans Thai Regular": "NotoSansThai[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Tifinagh Regular": "NotoSansTifinagh-Regular.ttf" ++ }, ++ { ++ "Noto Sans Ugaritic Regular": "NotoSansUgaritic-Regular.ttf" ++ }, ++ { ++ "Noto Sans Vai Regular": "NotoSansVai-Regular.ttf" ++ }, ++ { ++ "Noto Sans Wancho Regular": "NotoSansWancho-Regular.ttf" ++ }, ++ { ++ "Noto Sans Warang Citi Regular": "NotoSansWarangCiti-Regular.ttf" ++ }, ++ { ++ "Noto Sans Yi Regular": "NotoSansYi-Regular.ttf" ++ }, ++ { ++ "Noto Sans Regular": "NotoSans[wdth,wght].ttf" ++ }, ++ { ++ "Noto Serif Ahom Regular": "NotoSerifAhom-Regular.ttf" ++ }, ++ { ++ "Noto Serif Armenian Regular": "NotoSerifArmenian[wdth,wght].ttf" ++ }, ++ { ++ "Noto Serif Bengali Regular": "NotoSerifBengali[wdth,wght].ttf" ++ }, ++ { ++ "Noto Serif CJK JP": "NotoSerifCJK-Regular.ttc" ++ }, ++ { ++ "Noto Serif Devanagari Regular": "NotoSerifDevanagari[wdth,wght].ttf" ++ }, ++ { ++ "Noto Serif Dogra Regular": "NotoSerifDogra-Regular.ttf" ++ }, ++ { ++ "Noto Serif Ethiopic Regular": "NotoSerifEthiopic[wdth,wght].ttf" ++ }, ++ { ++ "Noto Serif Georgian Regular": "NotoSerifGeorgian[wdth,wght].ttf" ++ }, ++ { ++ "Noto Serif Gujarati Regular": "NotoSerifGujarati[wght].ttf" ++ }, ++ { ++ "Noto Serif Gurmukhi Regular": "NotoSerifGurmukhi[wght].ttf" ++ }, ++ { ++ "Noto Serif Hebrew Regular": "NotoSerifHebrew[wdth,wght].ttf" ++ }, ++ { ++ "Noto Serif Kannada Regular": "NotoSerifKannada[wght].ttf" ++ }, ++ { ++ "Noto Serif Khmer Regular": "NotoSerifKhmer[wdth,wght].ttf" ++ }, ++ { ++ "Noto Serif Lao Regular": "NotoSerifLao[wdth,wght].ttf" ++ }, ++ { ++ "Noto Serif Malayalam Regular": "NotoSerifMalayalam[wght].ttf" ++ }, ++ { ++ "Noto Serif Myanmar Regular": "NotoSerifMyanmar[wdth,wght].ttf" ++ }, ++ { ++ "Noto Serif Sinhala Regular": "NotoSerifSinhala[wdth,wght].ttf" ++ }, ++ { ++ "Noto Serif Tamil Regular": "NotoSerifTamil[wdth,wght].ttf" ++ }, ++ { ++ "Noto Serif Telugu Regular": "NotoSerifTelugu[wght].ttf" ++ }, ++ { ++ "Noto Serif Thai Regular": "NotoSerifThai[wdth,wght].ttf" ++ }, ++ { ++ "Noto Serif Tibetan Regular": "NotoSerifTibetan[wght].ttf" ++ }, ++ { ++ "Noto Serif Yezidi Regular": "NotoSerifYezidi[wght].ttf" ++ }, ++ { ++ "Noto Serif Regular": "NotoSerif[wdth,wght].ttf" ++ }, ++ { ++ "Noto Sans Regular": "Roboto-Regular.ttf" ++ }, ++ { ++ "Noto Sans Math Regular": "NotoSansMath-Regular.ttf" ++ }, ++ { ++ "FangS-SC": "FangS-SC.ttf" ++ }, ++ { ++ "仿宋-简": "FangS-SC.ttf" ++ }, ++ { ++ "FT Thymes Regular": "FTThymes-Regular.ttf" ++ }, ++ { ++ "HeiT-SC": "HeiT-SC-Regular.ttf" ++ }, ++ { ++ "ShuS-SC ": "ShuS-SC.ttf" ++ }, ++ { ++ "书宋-简": "ShuS-SC.ttf" ++ }, ++ { ++ "KaiT-SC": "KaiT-SC.ttf" ++ }, ++ { ++ "楷体-简": "KaiT-SC.ttf" + } + ] +} @@ -3812,6 +5043,3 @@ index fca2f34ded..65955a7041 100644 OutputStream* rawOut = fOut; StringStream body; fOut = &body; --- -2.25.1 - -- Gitee From 62e5e71a67055edc6404289d829d8afea18bddcb Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 16 Dec 2024 10:34:47 +0800 Subject: [PATCH 06/15] =?UTF-8?q?fix:=E4=BC=98=E5=8C=96=E5=9D=90=E6=A0=87?= =?UTF-8?q?=E6=98=A0=E5=B0=84=E7=AE=97=E6=B3=95=E3=80=81=E7=84=A6=E7=82=B9?= =?UTF-8?q?=E7=BB=BF=E6=A1=86=E8=B7=9F=E9=9A=8F=E5=8F=8C=E6=8C=87=E6=BB=91?= =?UTF-8?q?=E5=8A=A8=E3=80=81=E4=BF=AE=E5=A4=8D=E5=A4=9A=E7=B2=92=E5=BA=A6?= =?UTF-8?q?=E5=AD=97=E9=87=8D=E6=98=BE=E7=A4=BA=E3=80=81=E9=87=8D=E6=9E=84?= =?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 --- shell/platform/ohos/BUILD.gn | 6 +- .../ohos_accessibility_bridge.cpp | 522 +++++++++++------- .../accessibility/ohos_accessibility_bridge.h | 39 +- shell/platform/ohos/utils/ohos_utils.cpp | 23 + shell/platform/ohos/utils/ohos_utils.h | 31 ++ 5 files changed, 418 insertions(+), 203 deletions(-) create mode 100644 shell/platform/ohos/utils/ohos_utils.cpp create mode 100644 shell/platform/ohos/utils/ohos_utils.h diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn index 84548cee19..982c45eab5 100644 --- a/shell/platform/ohos/BUILD.gn +++ b/shell/platform/ohos/BUILD.gn @@ -90,7 +90,8 @@ source_set("flutter_ohos_sources") { "./accessibility/ohos_accessibility_manager.h", "./accessibility/native_accessibility_channel.h", "./accessibility/ohos_accessibility_ddl.h", - "./utils/ddl_utils.h" + "./utils/ddl_utils.h", + "./utils/ohos_utils.h" ] #configs += [ "//flutter/shell/platform/ohos/config:gtk" ] @@ -126,7 +127,8 @@ source_set("flutter_ohos_sources") { "./accessibility/ohos_accessibility_features.cpp", "./accessibility/ohos_accessibility_manager.cpp", "./accessibility/native_accessibility_channel.cpp", - "./accessibility/ohos_accessibility_ddl.cpp" + "./accessibility/ohos_accessibility_ddl.cpp", + "./utils/ohos_utils.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 2b9f261cd9..d250610dac 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -15,6 +15,7 @@ #include "ohos_accessibility_bridge.h" #include #include +#include #include #include #include @@ -91,20 +92,17 @@ void OhosAccessibilityBridge::updateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { - FML_DLOG(INFO) << ("OhosAccessibilityBridge::UpdateSemantics()"); - + FML_DLOG(INFO) << "OhosAccessibilityBridge::UpdateSemantics()"; + isFlutterSemanticsTreeUpdated = true; std::vector updatedFlutterNodes; - // 当flutter页面路由更新时,自动请求id=0节点组件获焦(规避滑动组件更新干扰) + // 当flutter页面状态更新(路由新页面)时,自动请求root节点组件获焦(规避滑动组件更新干扰) if (IS_FLUTTER_NAVIGATE) { + Flutter_SendAccessibilityAsyncEvent(0, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_STATE_UPDATE); RequestFocusWhenPageUpdate(0); IS_FLUTTER_NAVIGATE = false; } - // 页面内容更新事件 - Flutter_SendAccessibilityAsyncEvent(0, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); - LOGD("Flutter_SendAccessibilityAsyncEvent -> PAGE_CONTENT_UPDATE"); - /** 获取并分析每个语义节点的更新属性 */ for (auto& item : update) { // 获取当前更新的节点node @@ -140,6 +138,10 @@ void OhosAccessibilityBridge::updateSemantics( } } + // 页面内容更新事件 + Flutter_SendAccessibilityAsyncEvent(0, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); + LOGD("Flutter_SendAccessibilityAsyncEvent -> PAGE_CONTENT_UPDATE"); + /* 针对更新后的节点进行事件处理 */ for (const auto& nodeEx: updatedFlutterNodes) { // 当滑动节点产生滑动,并执行滑动处理 @@ -157,6 +159,11 @@ void OhosAccessibilityBridge::updateSemantics( // flutter滑动组件滑动处理逻辑 FlutterScrollExecution(nodeEx, _elementInfo); + // 屏幕朗读状态下双指滑动,获焦节点绿框实时跟随节点滑动 + Flutter_SendAccessibilityAsyncEvent( + static_cast(accessibilityFocusedNode.id), + ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_FOCUS_NODE_UPDATE); + void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); if (OH_ArkUI_DestoryAccessibilityElementInfo == nullptr) { @@ -239,6 +246,15 @@ void OhosAccessibilityBridge::FlutterScrollExecution( } ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, startItemIndex)); + // 设置当前获焦节点的当前index + int32_t currItemIndex = accessibilityFocusedNode.id; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex"); + if (OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex(elementInfoFromList, currItemIndex)); + // 计算当前滑动位置页面的可见子滑动节点数量 int visibleChildren = 0; // handle hidden children at the beginning and end of the list. @@ -633,7 +649,7 @@ void OhosAccessibilityBridge::FlutterTreeToArkuiTree( int32_t OhosAccessibilityBridge::GetParentId(int64_t elementId) { if (!g_parentChildIdVec.size()) { - FML_DLOG(INFO) << "OhosAccessibilityBridge::GetParentId parentChildIdMap.size()=0"; + FML_DLOG(WARNING) << "OhosAccessibilityBridge::GetParentId parentChildIdMap.size()=0"; return ARKUI_ACCESSIBILITY_ROOT_PARENT_ID; } if (elementId == -1) { @@ -755,11 +771,10 @@ void OhosAccessibilityBridge::FlutterRelativeRectToScreenRect( newRight > realParentRight || newBottom > realParentBottom || newLeft >= newRight || newTop >= newBottom || newRight > rootWidth || newBottom > rootHeight; - if (IS_OVER_SCREEN_AREA) { - FML_DLOG(ERROR) << "RelativeRectToScreenRect -> childRect exceeds parentRect {Id: " - << currNode.id << ", (" << newLeft << ", " << newTop - << ", " << newRight << ", " << newBottom << ")}"; + FML_DLOG(WARNING) << "RelativeRectToScreenRect -> childRect exceeds parentRect {Id: " + << currNode.id << ", (" << newLeft << ", " << newTop + << ", " << newRight << ", " << newBottom << ")}"; // 防止滑动场景下绿框坐标超出屏幕范围,进行正则化处理 SetAbsoluteScreenRect(currNode, rootWidth, rootHeight, 0, 0); } else { @@ -998,7 +1013,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( actions[9].actionType = ArkUI_Accessibility_ActionType:: ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION; actions[9].description = "光标位置设置"; - + ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions) ); @@ -1533,6 +1548,282 @@ void OhosAccessibilityBridge::DispatchSemanticsAction( fml::MallocMapping()); } +/** + * flutter按钮节点双击跳转新页面时,发送页面更新事件 + */ +void OhosAccessibilityBridge::DoubleClickRouteToNewPage(SemanticsNodeExtent node) +{ + if (isFlutterSemanticsTreeUpdated && node.HasFlag(FLAGS_::kIsButton)) { + RequestFocusWhenPageUpdate(0); + // isFlutterSemanticsTreeUpdated = false; + } +} + +/** + * perform click action in accessibility status + */ +void OhosAccessibilityBridge::PerformClickAction( + int64_t elementId, + ArkUI_Accessibility_ActionType action, + SemanticsNodeExtent flutterNode) +{ + /** Click event, sent after the UI component responds. 1 */ + auto clickEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_CLICKED; + Flutter_SendAccessibilityAsyncEvent(elementId, clickEventType); + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: click(" << action + << ")" << " event: click(" << clickEventType << ")"; + auto flutterTapAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), flutterTapAction, {}); + // double click at button-like node for pushing page update + DoubleClickRouteToNewPage(flutterNode); +} + +/** + * perform long-press action in accessibility status + */ +void OhosAccessibilityBridge::PerformLongClickAction( + int64_t elementId, + ArkUI_Accessibility_ActionType action, + SemanticsNodeExtent flutterNode) +{ + /** Long click event, sent after the UI component responds. 2 */ + auto longClickEventType = ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_LONG_CLICKED; + Flutter_SendAccessibilityAsyncEvent(elementId, longClickEventType); + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: longclick(" + << action << ")" << " event: longclick(" + << longClickEventType << ")"; + auto flutterLongPressAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), flutterLongPressAction, {}); +} + +/** + * perform focus acquisition in accessibility status + */ +void OhosAccessibilityBridge::PerformGainFocusnAction( + int64_t elementId, + ArkUI_Accessibility_ActionType action, + SemanticsNodeExtent flutterNode) +{ + // 感知获焦flutter节点 + accessibilityFocusedNode = flutterNode; + // 解析arkui的获焦 -> flutter对应节点的获焦 + auto flutterGainFocusAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), + flutterGainFocusAction, {}); + // Accessibility focus event, sent after the UI component responds. 32768 + auto focusEventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; + Flutter_SendAccessibilityAsyncEvent(elementId, focusEventType); + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: focus(" << action + << ")" << " event: focus(" << focusEventType << ")"; + + if (flutterNode.HasAction(ACTIONS_::kIncrease) || + flutterNode.HasAction(ACTIONS_::kDecrease)) { + Flutter_SendAccessibilityAsyncEvent( + elementId, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + } +} + +/** + * perform focus clearance in accessibility status + */ +void OhosAccessibilityBridge::PerformClearFocusAction( + int64_t elementId, + ArkUI_Accessibility_ActionType action, + SemanticsNodeExtent flutterNode) +{ + // 解析arkui的失焦 -> flutter对应节点的失焦 + auto flutterLoseFocusAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), flutterLoseFocusAction, {}); + /** Accessibility focus cleared event, sent after the UI component + * responds. 65536 */ + auto clearFocusEventType = ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED; + Flutter_SendAccessibilityAsyncEvent(elementId, clearFocusEventType); + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: clearfocus(" + << action << ")" << " event: clearfocus(" + << clearFocusEventType << ")"; +} + +/** + * perform scroll forward in accessibility status + */ +void OhosAccessibilityBridge::PerformScrollUpAction( + int64_t elementId, + ArkUI_Accessibility_ActionType action, + SemanticsNodeExtent flutterNode) +{ + // flutter scroll forward with different situations + if (flutterNode.HasAction(ACTIONS_::kScrollUp)) { + auto flutterScrollUpAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), flutterScrollUpAction, {}); + } else if (flutterNode.HasAction(ACTIONS_::kScrollLeft)) { + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kScrollLeft, {}); + } else if (flutterNode.HasAction(ACTIONS_::kIncrease)) { + flutterNode.value = flutterNode.increasedValue; + flutterNode.valueAttributes = flutterNode.increasedValueAttributes; + + Flutter_SendAccessibilityAsyncEvent( + elementId, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kIncrease, {}); + } + std::string currComponetType = GetNodeComponentType(flutterNode); + if (Contains(currComponetType, SCROLL_WIDGET_NAME)) { + /** Scrolled event, sent when a scrollable component experiences a scroll event. 4096 */ + ArkUI_AccessibilityEventType scrollEventType1 = + ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); + FML_DLOG(INFO) + << "ExecuteAccessibilityAction -> action: scroll forward(" << action + << ")" << " event: scroll forward(" << scrollEventType1 << ")"; + } +} + +/** + * perform scroll backward in accessibility status + */ +void OhosAccessibilityBridge::PerformScrollDownAction( + int64_t elementId, + ArkUI_Accessibility_ActionType action, + SemanticsNodeExtent flutterNode) +{ + // flutter scroll down with different situations + if (flutterNode.HasAction(ACTIONS_::kScrollDown)) { + auto flutterScrollDownAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(static_cast(elementId), flutterScrollDownAction, {}); + } else if (flutterNode.HasAction(ACTIONS_::kScrollRight)) { + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kScrollRight, {}); + } else if (flutterNode.HasAction(ACTIONS_::kDecrease)) { + flutterNode.value = flutterNode.decreasedValue; + flutterNode.valueAttributes = flutterNode.decreasedValueAttributes; + + Flutter_SendAccessibilityAsyncEvent( + elementId, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kDecrease, {}); + } + std::string currComponetType = GetNodeComponentType(flutterNode); + if (Contains(currComponetType, SCROLL_WIDGET_NAME)) { + /** Scrolled event, sent when a scrollable component experiences a + * scroll event. 4096 */ + ArkUI_AccessibilityEventType scrollEventType1 = + ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); + FML_DLOG(INFO) + << "ExecuteAccessibilityAction -> action: scroll forward(" << action + << ")" << " event: scroll forward(" << scrollEventType1 << ")"; + } +} +/** + * perform invalid action in accessibility status + */ +void OhosAccessibilityBridge::PerformClipboardAction( + int64_t elementId, + ArkUI_Accessibility_ActionType action) +{ + if (action == ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY) { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: copy(" << action << ")"; + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCopy, {}); + } else if (action == ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE) { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: paste(" << action << ")"; + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kPaste, {}); + } else { + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: cut(" << action << ")"; + DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCut, {}); + } +} +/** + * perform invalid action in accessibility status + */ +void OhosAccessibilityBridge::PerformInvalidAction( + int64_t elementId, + ArkUI_Accessibility_ActionType action, + SemanticsNodeExtent flutterNode) +{ + /** Invalid event. 0 */ + ArkUI_AccessibilityEventType invalidEventType = + ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_INVALID; + Flutter_SendAccessibilityAsyncEvent(elementId, invalidEventType); + FML_DLOG(ERROR) << "ExecuteAccessibilityAction -> action: invalid(" + << action << ")" << " event: innvalid(" + << invalidEventType << ")"; +} +/** + * 设置输入框文本 + */ +void OhosAccessibilityBridge::PerformSetText( + SemanticsNodeExtent flutterNode, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments) +{ + if (OH_GetSdkApiVersion() >= 13) { + int32_t (*OH_ArkUI_FindAccessibilityActionArgumentByKey)(ArkUI_AccessibilityActionArguments*, const char*, char**) = + OhosAccessibilityDDL::DLLoadGetFindActionArgs("OH_ArkUI_FindAccessibilityActionArgumentByKey"); + if (OH_ArkUI_FindAccessibilityActionArgumentByKey == nullptr) { + LOGE("OH_ArkUI_FindAccessibilityActionArgumentByKey is null, %{public}s", dlerror()); + } + const char* key_setText = "setText"; + const char* valueStr = flutterNode.value.c_str(); + char* newValue = strdup(valueStr); + char** value = &newValue; + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key_setText, value)); + if (newValue == nullptr) { + LOGE("PerformSetText -> OH_ArkUI_FindAccessibilityActionArgumentByKey get null value"); + } + auto flutterSetTextAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(flutterNode.id, flutterSetTextAction, fml::MallocMapping::Copy(newValue, strlen(newValue))); + flutterNode.value = newValue; + flutterNode.valueAttributes = {}; + LOGI("ExecuteAccessibilityAction -> action: set text(%{public}d), newText=%{public}s", action, newValue); + } +} + +/** + * perform cursor position setting in accessibility status + */ +void OhosAccessibilityBridge::PerformSelectText( + SemanticsNodeExtent flutterNode, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments) +{ + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: select text(" << action << ")"; + return; +} + +/** + * perform cursor position setting in accessibility status + */ +void OhosAccessibilityBridge::PerformSetCursorPosition( + SemanticsNodeExtent flutterNode, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments) +{ + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: set cursor position (" << action << ")"; + return; +} + +/** + * perform custom action in accessibility status + */ +void OhosAccessibilityBridge::PerformCustomAction( + SemanticsNodeExtent flutterNode, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments) +{ + FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: custom action (" << action << ")"; + DispatchSemanticsAction(flutterNode.id, ACTIONS_::kCustomAction, {}); + return; +} + +/** + * perform show on screen action in accessibility status + */ +void OhosAccessibilityBridge::PerformShowOnScreenAction(SemanticsNodeExtent flutterNode) +{ + if (!IsNodeShowOnScreen(flutterNode)) { + DispatchSemanticsAction(flutterNode.id, ACTIONS_::kShowOnScreen, {}); + } +} + /** * 执行语义动作解析,当FindAccessibilityNodeInfosById找到相应的elementinfo时才会触发该回调函数 */ @@ -1543,9 +1834,9 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( int32_t requestId) { FML_DLOG(INFO) << "ExecuteAccessibilityAction input-params-> elementId=" - << elementId << " action=" << action - << " requestId=" << requestId - << " *actionArguments=" << actionArguments; + << elementId << " action=" << action + << " requestId=" << requestId + << " *actionArguments=" << actionArguments; if (actionArguments == nullptr) { FML_DLOG(ERROR) << "OhosAccessibilityBridge::ExecuteAccessibilityAction " @@ -1559,205 +1850,84 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( LOGE("ExecuteAccessibilityAction: GetFlutterSemanticsNode id=%{public}ld is null", elementId); } - // 若当前节点为非屏幕显示状态,将其显示在屏幕上 - if (!IsNodeShowOnScreen(flutterNode)) { - DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kShowOnScreen, {}); - } + /** + * 将被遮挡的flutter节点显示在屏幕上 + * @NOTE: arkui无障碍缺少showOnScreen动作 + */ + PerformShowOnScreenAction(flutterNode); // 根据当前elementid和无障碍动作类型,发送无障碍事件 switch (action) { /** Response to a click. 16 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: { - /** Click event, sent after the UI component responds. 1 */ - auto clickEventType = ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_CLICKED; - Flutter_SendAccessibilityAsyncEvent(elementId, clickEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: click(" << action - << ")" << " event: click(" << clickEventType << ")"; - // 解析arkui的屏幕点击 -> flutter对应节点的屏幕点击 - auto flutterTapAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), flutterTapAction, - {}); + PerformClickAction(elementId, action, flutterNode); break; } /** Response to a long click. 32 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_LONG_CLICK: { - /** Long click event, sent after the UI component responds. 2 */ - auto longClickEventType = ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_LONG_CLICKED; - Flutter_SendAccessibilityAsyncEvent(elementId, longClickEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: longclick(" - << action << ")" << " event: longclick(" - << longClickEventType << ")"; - // 解析arkui的屏幕动作 -> flutter对应节点的屏幕动作 - auto flutterLongPressAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), - flutterLongPressAction, {}); + PerformLongClickAction(elementId, action, flutterNode); break; } /** Accessibility focus acquisition. 64 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: { - // 感知获焦flutter节点 - accessibilityFocusedNode = flutterNode; - // 解析arkui的获焦 -> flutter对应节点的获焦 - auto flutterGainFocusAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), - flutterGainFocusAction, {}); - // Accessibility focus event, sent after the UI component responds. 32768 - auto focusEventType = ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED; - Flutter_SendAccessibilityAsyncEvent(elementId, focusEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: focus(" << action - << ")" << " event: focus(" << focusEventType << ")"; - - if (flutterNode.HasAction(ACTIONS_::kIncrease) || - flutterNode.HasAction(ACTIONS_::kDecrease)) { - Flutter_SendAccessibilityAsyncEvent( - elementId, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); - } + PerformGainFocusnAction(elementId, action, flutterNode); break; } /** Accessibility focus clearance. 128 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: { - // 解析arkui的失焦 -> flutter对应节点的失焦 - auto flutterLoseFocusAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), - flutterLoseFocusAction, {}); - /** Accessibility focus cleared event, sent after the UI component - * responds. 65536 */ - auto clearFocusEventType = ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUS_CLEARED; - Flutter_SendAccessibilityAsyncEvent(elementId, clearFocusEventType); - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: clearfocus(" - << action << ")" << " event: clearfocus(" - << clearFocusEventType << ")"; + PerformClearFocusAction(elementId, action, flutterNode); break; } /** Forward scroll action. 256 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_FORWARD: { - // flutter scroll forward with different situations - if (flutterNode.HasAction(ACTIONS_::kScrollUp)) { - auto flutterScrollUpAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), - flutterScrollUpAction, {}); - } else if (flutterNode.HasAction(ACTIONS_::kScrollLeft)) { - DispatchSemanticsAction(static_cast(elementId), - ACTIONS_::kScrollLeft, {}); - } else if (flutterNode.HasAction(ACTIONS_::kIncrease)) { - flutterNode.value = flutterNode.increasedValue; - flutterNode.valueAttributes = flutterNode.increasedValueAttributes; - - Flutter_SendAccessibilityAsyncEvent( - elementId, ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); - DispatchSemanticsAction(static_cast(elementId), - ACTIONS_::kIncrease, {}); - } - std::string currComponetType = GetNodeComponentType(flutterNode); - if (Contains(currComponetType, SCROLL_WIDGET_NAME)) { - /** Scrolled event, sent when a scrollable component experiences a - * scroll event. 4096 */ - ArkUI_AccessibilityEventType scrollEventType1 = - ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; - Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); - FML_DLOG(INFO) - << "ExecuteAccessibilityAction -> action: scroll forward(" << action - << ")" << " event: scroll forward(" << scrollEventType1 << ")"; - } + PerformScrollUpAction(elementId, action, flutterNode); break; } /** Backward scroll action. 512 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: { - // flutter scroll down with different situations - if (flutterNode.HasAction(ACTIONS_::kScrollDown)) { - auto flutterScrollDownAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(static_cast(elementId), - flutterScrollDownAction, {}); - } else if (flutterNode.HasAction(ACTIONS_::kScrollRight)) { - DispatchSemanticsAction(static_cast(elementId), - ACTIONS_::kScrollRight, {}); - } else if (flutterNode.HasAction(ACTIONS_::kDecrease)) { - flutterNode.value = flutterNode.decreasedValue; - flutterNode.valueAttributes = flutterNode.decreasedValueAttributes; - - Flutter_SendAccessibilityAsyncEvent( - elementId, ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); - DispatchSemanticsAction(static_cast(elementId), - ACTIONS_::kDecrease, {}); - } - std::string currComponetType = GetNodeComponentType(flutterNode); - if (Contains(currComponetType, SCROLL_WIDGET_NAME)) { - /** Scrolled event, sent when a scrollable component experiences a - * scroll event. 4096 */ - ArkUI_AccessibilityEventType scrollEventType1 = - ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; - Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); - FML_DLOG(INFO) - << "ExecuteAccessibilityAction -> action: scroll forward(" << action - << ")" << " event: scroll forward(" << scrollEventType1 << ")"; - } + PerformScrollDownAction(elementId, action, flutterNode); break; } /** Copy action for text content. 1024 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: copy(" << action - << ")"; - DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCopy, {}); + PerformClipboardAction(elementId, action); break; } /** Paste action for text content. 2048 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: paste(" << action - << ")"; - DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kPaste, {}); + PerformClipboardAction(elementId, action); break; } /** Cut action for text content. 4096 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: cut(" << action << ")"; - DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kCut, {}); + PerformClipboardAction(elementId, action); break; } /** Text selection action, requiring the setting of selectTextBegin, * TextEnd, and TextInForward parameters to select a text * segment in the text box. 8192 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: select text(" - << action << ")"; - // 输入框文本选择操作 PerformSelectText(flutterNode, action, actionArguments); break; } /** Text content setting action. 16384 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: { - FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: set text(" - << action << ")"; - // 输入框设置文本 PerformSetText(flutterNode, action, actionArguments); break; } /** Cursor position setting action. 1048576 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION: { - FML_DLOG(INFO) - << "ExecuteAccessibilityAction -> action: set cursor position(" - << action << ")"; + PerformSetCursorPosition(flutterNode, action, actionArguments); break; } /** Invalid action. 0 */ case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID: { - /** Invalid event. 0 */ - ArkUI_AccessibilityEventType invalidEventType = - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_INVALID; - Flutter_SendAccessibilityAsyncEvent(elementId, invalidEventType); - FML_DLOG(ERROR) << "ExecuteAccessibilityAction -> action: invalid(" - << action << ")" << " event: innvalid(" - << invalidEventType << ")"; + PerformInvalidAction(elementId, action, flutterNode); break; } default: { /** custom semantics action */ + PerformCustomAction(flutterNode, action, actionArguments); } } FML_DLOG(INFO) << "--- ExecuteAccessibilityAction is end ---"; @@ -1848,9 +2018,6 @@ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( 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; @@ -1860,7 +2027,7 @@ flutter::SemanticsAction OhosAccessibilityBridge::ArkuiActionsToFlutterActions( return ACTIONS_::kSetText; default: - // might not match to the valid action in arkui + // might not match to the valid action in arkui return ACTIONS_::kCustomAction; } } @@ -1965,45 +2132,6 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( return; } -/** - * 设置输入框文本 - */ -void OhosAccessibilityBridge::PerformSetText( - SemanticsNodeExtent flutterNode, - ArkUI_Accessibility_ActionType action, - ArkUI_AccessibilityActionArguments* actionArguments) -{ - // 获取特殊动作参数 - // int32_t (*OH_ArkUI_FindAccessibilityActionArgumentByKey)(ArkUI_AccessibilityActionArguments*, const char*, char**) = - // OhosAccessibilityDDL::DLLoadGetFindActionArgs("OH_ArkUI_FindAccessibilityActionArgumentByKey"); - // if (OH_ArkUI_FindAccessibilityActionArgumentByKey == nullptr) { - // LOGE("OH_ArkUI_FindAccessibilityActionArgumentByKey is null, %{public}s", dlerror()); - // } - // const char* key_setText = "setText"; - // char* newValue = "debug"; - // char** value = &newValue; - // ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key_setText, value)); - // if (newValue == nullptr) { - // // newValue = "888"; - // LOGE("PerformSetText -> OH_ArkUI_FindAccessibilityActionArgumentByKey get null value"); - // } - auto flutterSetTextAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(flutterNode.id, flutterSetTextAction, {}); - flutterNode.value = "debug"; - flutterNode.valueAttributes = {}; -} - -/** - * 设置文本选择范畴 - */ -void OhosAccessibilityBridge::PerformSelectText( - SemanticsNodeExtent flutterNode, - ArkUI_Accessibility_ActionType action, - ArkUI_AccessibilityActionArguments* actionArguments) -{ - return; -} - /** * 获取当前flutter节点的组件类型,并映射为arkui组件 */ diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 445093c0c9..08d196aee1 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -160,6 +160,7 @@ private: std::unordered_map g_actions_mp; std::vector g_flutterNavigationVec; + bool isFlutterSemanticsTreeUpdated = false; SemanticsNodeExtent inputFocusedNode; SemanticsNodeExtent lastInputFocusedNode; SemanticsNodeExtent accessibilityFocusedNode; @@ -262,12 +263,43 @@ private: bool IsTextField(SemanticsNodeExtent flutterNode); bool IsSlider(SemanticsNodeExtent flutterNode); bool IsScrollableWidget(SemanticsNodeExtent flutterNode); + + void PerformClickAction(int64_t elementId, + ArkUI_Accessibility_ActionType action, + SemanticsNodeExtent flutterNode); + void PerformLongClickAction(int64_t elementId, + ArkUI_Accessibility_ActionType action, + SemanticsNodeExtent flutterNode); + void PerformGainFocusnAction(int64_t elementId, + ArkUI_Accessibility_ActionType action, + SemanticsNodeExtent flutterNode); + void PerformClearFocusAction(int64_t elementId, + ArkUI_Accessibility_ActionType action, + SemanticsNodeExtent flutterNode); + void PerformScrollUpAction(int64_t elementId, + ArkUI_Accessibility_ActionType action, + SemanticsNodeExtent flutterNode); + void PerformScrollDownAction(int64_t elementId, + ArkUI_Accessibility_ActionType action, + SemanticsNodeExtent flutterNode); + void PerformClipboardAction(int64_t elementId, + ArkUI_Accessibility_ActionType action); + void PerformInvalidAction(int64_t elementId, + ArkUI_Accessibility_ActionType action, + SemanticsNodeExtent flutterNode); void PerformSetText(SemanticsNodeExtent flutterNode, ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments); void PerformSelectText(SemanticsNodeExtent flutterNode, - ArkUI_Accessibility_ActionType action, - ArkUI_AccessibilityActionArguments* actionArguments); + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments); + void PerformSetCursorPosition(SemanticsNodeExtent flutterNode, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments); + void PerformCustomAction(SemanticsNodeExtent flutterNode, + ArkUI_Accessibility_ActionType action, + ArkUI_AccessibilityActionArguments* actionArguments); + void PerformShowOnScreenAction(SemanticsNodeExtent flutterNode); void AddRouteNodes(std::vector edges, SemanticsNodeExtent node); @@ -283,8 +315,7 @@ private: void RequestFocusWhenPageUpdate(int32_t requestFocusId); bool Contains(const std::string source, const std::string target); std::pair GetRealScaleFactor(); - void FlutterSemanticsTreeUpdateCallOnce(); - + void DoubleClickRouteToNewPage(SemanticsNodeExtent node); void GetSemanticsDebugInfo(); }; diff --git a/shell/platform/ohos/utils/ohos_utils.cpp b/shell/platform/ohos/utils/ohos_utils.cpp new file mode 100644 index 0000000000..d56f8f579e --- /dev/null +++ b/shell/platform/ohos/utils/ohos_utils.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ohos_utils.h" + +namespace flutter { + +OHOSUtils::OHOSUtils() {}; +OHOSUtils::~OHOSUtils() {}; + + +} \ No newline at end of file diff --git a/shell/platform/ohos/utils/ohos_utils.h b/shell/platform/ohos/utils/ohos_utils.h new file mode 100644 index 0000000000..938cb07906 --- /dev/null +++ b/shell/platform/ohos/utils/ohos_utils.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_UTILS_H +#define OHOS_UTILS_H + +namespace flutter { + +class OHOSUtils { +public: + OHOSUtils(); + ~OHOSUtils(); + +}; + +} + + +#endif -- Gitee From 36640ed21311a555cd5465887c9a75627d7db256 Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 16 Dec 2024 15:02:46 +0800 Subject: [PATCH 07/15] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E9=9D=99=E6=80=81=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../native_accessibility_channel.cpp | 2 +- .../ohos_accessibility_bridge.cpp | 562 ++++++------------ .../accessibility/ohos_accessibility_bridge.h | 31 +- shell/platform/ohos/utils/ohos_utils.cpp | 9 +- shell/platform/ohos/utils/ohos_utils.h | 4 +- 5 files changed, 214 insertions(+), 394 deletions(-) diff --git a/shell/platform/ohos/accessibility/native_accessibility_channel.cpp b/shell/platform/ohos/accessibility/native_accessibility_channel.cpp index 1d3e8a7a3a..d8ba25cb99 100644 --- a/shell/platform/ohos/accessibility/native_accessibility_channel.cpp +++ b/shell/platform/ohos/accessibility/native_accessibility_channel.cpp @@ -84,7 +84,7 @@ namespace flutter { flutter::CustomAccessibilityActionUpdates actions) { auto ohos_a11y_bridge = OhosAccessibilityBridge::GetInstance(); - ohos_a11y_bridge->updateSemantics(update, actions); + ohos_a11y_bridge->UpdateSemantics(update, actions); } /** diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index d250610dac..8fd91391fd 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -14,8 +14,7 @@ */ #include "ohos_accessibility_bridge.h" #include -#include -#include +#include #include #include #include @@ -31,15 +30,14 @@ #define ARKUI_FAILED_CODE -1 #define ARKUI_BAD_PARAM_CODE -2 #define ARKUI_OOM_CODE -3 -#define FUNCTION_NAME_STR(func) #func -#define ARKUI_ACCESSIBILITY_CALL_CHECK(X) \ - do { \ - int32_t RET = X; \ - if (RET != ARKUI_SUCCEED_CODE) { \ - LOGE("Failed function %{public}s call, error code:%{public}d", \ - FUNCTION_NAME_STR(X), RET); \ - } \ - } while (false) \ +#define ARKUI_ACCESSIBILITY_CALL_CHECK(X) \ + do { \ + int32_t RET = X; \ + if (RET != ARKUI_SUCCEED_CODE) { \ + LOGE("Failed function %{public}s call, error code:%{public}d", \ + #X, RET); \ + } \ + } while (false) \ namespace flutter { @@ -88,7 +86,7 @@ void OhosAccessibilityBridge::SetNativeShellHolderId(int64_t id) * 从dart侧传递到c++侧的flutter无障碍语义树节点更新过程, * 路由新页面、滑动页面等操作会自动触发该语义树的更新 */ -void OhosAccessibilityBridge::updateSemantics( +void OhosAccessibilityBridge::UpdateSemantics( flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) { @@ -139,7 +137,9 @@ void OhosAccessibilityBridge::updateSemantics( } // 页面内容更新事件 - Flutter_SendAccessibilityAsyncEvent(0, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); + Flutter_SendAccessibilityAsyncEvent(0, + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); LOGD("Flutter_SendAccessibilityAsyncEvent -> PAGE_CONTENT_UPDATE"); /* 针对更新后的节点进行事件处理 */ @@ -164,7 +164,7 @@ void OhosAccessibilityBridge::updateSemantics( static_cast(accessibilityFocusedNode.id), ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_FOCUS_NODE_UPDATE); - void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = + void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); if (OH_ArkUI_DestoryAccessibilityElementInfo == nullptr) { LOGE("OH_ArkUI_DestoryAccessibilityElementInfo is null, %{public}s", dlerror()); @@ -178,7 +178,8 @@ void OhosAccessibilityBridge::updateSemantics( if (nodeEx.HasFlag(FLAGS_::kIsLiveRegion) && HasChangedLabel(nodeEx)) { FML_DLOG(INFO) << "UpdateSemantics -> page content update, nodeEx.id=" << nodeEx.id; Flutter_SendAccessibilityAsyncEvent(static_cast(nodeEx.id), - ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); LOGD("Flutter_SendAccessibilityAsyncEvent -> PAGE_CONTENT_UPDATE"); } } @@ -363,7 +364,7 @@ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate(int32_t requestFocusId) OH_ArkUI_DestoryAccessibilityEventInfo(reqFocusEventInfo); reqFocusEventInfo = nullptr; - void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = + void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); if (OH_ArkUI_DestoryAccessibilityElementInfo == nullptr) { LOGE("OH_ArkUI_DestoryAccessibilityElementInfo is null, %{public}s", dlerror()); @@ -464,185 +465,6 @@ SemanticsNodeExtent OhosAccessibilityBridge::GetFlutterSemanticsNode( } } -/** - * flutter的语义节点初始化配置给arkui创建的elementInfos - */ -void OhosAccessibilityBridge::FlutterTreeToArkuiTree( - ArkUI_AccessibilityElementInfoList* elementInfoList) -{ - if (g_flutterSemanticsTree.size() == 0) { - FML_DLOG(ERROR) << "OhosAccessibilityBridge::FlutterTreeToArkuiTree " - "g_flutterSemanticsTree.size() = 0"; - return; - } - if (OH_GetSdkApiVersion() >= 13) { - // 将flutter语义节点树传递给arkui的无障碍elementinfo - for (const auto& item : g_flutterSemanticsTree) { - SemanticsNodeExtent flutterNode = item.second; - - // 创建elementinfo,系统自动加入到elementinfolist - ArkUI_AccessibilityElementInfo* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = - OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); - if (OH_ArkUI_AddAndGetAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_AddAndGetAccessibilityElementInfo is null, %{public}s", dlerror()); - } - ArkUI_AccessibilityElementInfo* elementInfo = - OH_ArkUI_AddAndGetAccessibilityElementInfo(elementInfoList); - if (elementInfo == nullptr) { - FML_DLOG(INFO) << "OhosAccessibilityBridge::FlutterTreeToArkuiTree " - "elementInfo is null"; - return; - } - // 设置elementinfo的屏幕坐标范围 - int32_t left = static_cast(flutterNode.rect.fLeft); - int32_t top = static_cast(flutterNode.rect.fTop); - int32_t right = static_cast(flutterNode.rect.fRight); - int32_t bottom = static_cast(flutterNode.rect.fBottom); - ArkUI_AccessibleRect rect = {left, top, right, bottom}; - - int32_t (*OH_ArkUI_AccessibilityElementInfoSetScreenRect)(ArkUI_AccessibilityElementInfo*, ArkUI_AccessibleRect*) = - OhosAccessibilityDDL::DLLoadSetElemSreenRectFunc("OH_ArkUI_AccessibilityElementInfoSetScreenRect"); - if (OH_ArkUI_AccessibilityElementInfoSetScreenRect == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetScreenRect is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfo, &rect) - ); - - // 设置elementinfo的action类型 - std::string widget_type = GetNodeComponentType(flutterNode); - FlutterSetElementInfoOperationActions(elementInfo, widget_type); - - // 设置elementid - int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = - OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetElementId"); - if (OH_ArkUI_AccessibilityElementInfoSetElementId == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetElementId is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfo, flutterNode.id) - ); - - // 设置父节点id - int32_t parentId = GetParentId(flutterNode.id); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetParentId)(ArkUI_AccessibilityElementInfo*, int32_t) = - OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetParentId"); - if (OH_ArkUI_AccessibilityElementInfoSetParentId == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetParentId is null, %{public}s", dlerror()); - } - if (flutterNode.id == 0) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, ARKUI_ACCESSIBILITY_ROOT_PARENT_ID) - ); - } else { - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfo, parentId)); - } - - // 设置孩子节点 - int32_t childCount = flutterNode.childrenInTraversalOrder.size(); - if (childCount > 0) { - auto childrenIdsVec = flutterNode.childrenInTraversalOrder; - std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); - int64_t childNodeIds[childCount]; - for (int32_t i = 0; i < childCount; i++) { - childNodeIds[i] = static_cast(childrenIdsVec[i]); - FML_DLOG(INFO) << "FlutterTreeToArkuiTree flutterNode.id= " - << flutterNode.id << " childCount= " << childCount - << " childNodeId=" << childNodeIds[i]; - } - int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = - OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); - if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfo, childCount, childNodeIds) - ); - } - - // 配置常用属性 - int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); - if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfo, true)); - - int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); - if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfo, true)); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetCheckable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetCheckable"); - if (OH_ArkUI_AccessibilityElementInfoSetCheckable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetCheckable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfo, true)); - - int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetFocusable"); - if (OH_ArkUI_AccessibilityElementInfoSetFocusable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetFocusable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfo, true)); - - int32_t (*OH_ArkUI_AccessibilityElementInfoSetVisible)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetVisible"); - if (OH_ArkUI_AccessibilityElementInfoSetVisible == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetVisible is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfo, true)); - - // 设置组件类型 - std::string componentTypeName = GetNodeComponentType(flutterNode); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = - OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetComponentType"); - if (OH_ArkUI_AccessibilityElementInfoSetComponentType == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetComponentType is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfo, componentTypeName.c_str()) - ); - - std::string contents = componentTypeName + "_content"; - int32_t (*OH_ArkUI_AccessibilityElementInfoSetContents)(ArkUI_AccessibilityElementInfo*, const char*) = - OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetContents"); - if (OH_ArkUI_AccessibilityElementInfoSetContents == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetContents is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetContents(elementInfo, contents.c_str()) - ); - - // 设置无障碍相关属性 - int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityText)(ArkUI_AccessibilityElementInfo*, const char*) = - OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText"); - if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityText == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfo, flutterNode.label.c_str()) - ); - - int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel)(ArkUI_AccessibilityElementInfo*, const char*) = - OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel"); - if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfo, "yes")); - - int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup"); - if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfo, false)); - } - } -} - /** * 获取当前elementid的父节点id */ @@ -797,162 +619,153 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( } FML_DLOG(INFO) << "FlutterNodeToElementInfoById elementId = " << elementId; - if (OH_GetSdkApiVersion() >= 13) { - // 当elementId = -1或0时,创建root节点 - if (elementId == 0 || elementId == -1) { - // 获取flutter的root节点 - SemanticsNodeExtent flutterNode = GetFlutterSemanticsNode(static_cast(0)); - if (flutterNode.isNull) { - LOGE("FlutterNodeToElementInfoById: GetFlutterSemanticsNode id=%{public}ld null", elementId); - } + // 当elementId = -1或0时,创建root节点 + if (elementId == 0 || elementId == -1) { + // 获取flutter的root节点 + SemanticsNodeExtent flutterNode = GetFlutterSemanticsNode(static_cast(0)); + if (flutterNode.isNull) { + LOGE("FlutterNodeToElementInfoById: GetFlutterSemanticsNode id=%{public}ld null", elementId); + } - // 设置elementinfo的屏幕坐标范围 - int32_t left = static_cast(flutterNode.rect.fLeft); - int32_t top = static_cast(flutterNode.rect.fTop); - int32_t right = static_cast(flutterNode.rect.fRight); - int32_t bottom = static_cast(flutterNode.rect.fBottom); - ArkUI_AccessibleRect rect = {left, top, right, bottom}; - int32_t (*OH_ArkUI_AccessibilityElementInfoSetScreenRect)(ArkUI_AccessibilityElementInfo*, ArkUI_AccessibleRect*) = - OhosAccessibilityDDL::DLLoadSetElemSreenRectFunc("OH_ArkUI_AccessibilityElementInfoSetScreenRect"); - if (OH_ArkUI_AccessibilityElementInfoSetScreenRect == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetScreenRect is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect) - ); + // 设置elementinfo的屏幕坐标范围 + int32_t left = static_cast(flutterNode.rect.fLeft); + int32_t top = static_cast(flutterNode.rect.fTop); + int32_t right = static_cast(flutterNode.rect.fRight); + int32_t bottom = static_cast(flutterNode.rect.fBottom); + ArkUI_AccessibleRect rect = {left, top, right, bottom}; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetScreenRect)(ArkUI_AccessibilityElementInfo*, ArkUI_AccessibleRect*) = + OhosAccessibilityDDL::DLLoadSetElemSreenRectFunc("OH_ArkUI_AccessibilityElementInfoSetScreenRect"); + if (OH_ArkUI_AccessibilityElementInfoSetScreenRect == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetScreenRect is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect) + ); - // 设置root节点的屏幕绝对坐标rect - SetAbsoluteScreenRect(flutterNode, left, top, right, bottom); + // 设置root节点的屏幕绝对坐标rect + SetAbsoluteScreenRect(flutterNode, left, top, right, bottom); - // 设置root节点的action类型 - FlutterSetElementInfoOperationActions(elementInfoFromList, OTHER_WIDGET_NAME); + // 设置root节点的action类型 + FlutterSetElementInfoOperationActions(elementInfoFromList, OTHER_WIDGET_NAME); - // 根据flutternode信息配置对应的elementinfo - int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = - OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetElementId"); - if (OH_ArkUI_AccessibilityElementInfoSetElementId == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetElementId is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, 0)); + // 根据flutternode信息配置对应的elementinfo + int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetElementId"); + if (OH_ArkUI_AccessibilityElementInfoSetElementId == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetElementId is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, 0)); - // NOTE: arkui无障碍子系统强制设置root的父节点id = -2100000 (严禁更改) - int32_t (*OH_ArkUI_AccessibilityElementInfoSetParentId)(ArkUI_AccessibilityElementInfo*, int32_t) = - OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetParentId"); - if (OH_ArkUI_AccessibilityElementInfoSetParentId == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetParentId is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, ARKUI_ACCESSIBILITY_ROOT_PARENT_ID) - ); + // NOTE: arkui无障碍子系统强制设置root的父节点id = -2100000 (严禁更改) + int32_t (*OH_ArkUI_AccessibilityElementInfoSetParentId)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetParentId"); + if (OH_ArkUI_AccessibilityElementInfoSetParentId == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetParentId is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, ARKUI_ACCESSIBILITY_ROOT_PARENT_ID) + ); - // 设置无障碍播报文本 - int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityText)(ArkUI_AccessibilityElementInfo*, const char*) = - OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText"); - if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityText == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( - elementInfoFromList, flutterNode.label.empty() ? flutterNode.value.c_str() : flutterNode.label.c_str()) - ); + // 设置无障碍播报文本 + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityText)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText"); + if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityText == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( + elementInfoFromList, flutterNode.label.empty() ? + flutterNode.value.c_str() : flutterNode.label.c_str()) + ); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel)(ArkUI_AccessibilityElementInfo*, const char*) = - OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel"); - if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes") - ); + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel"); + if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes") + ); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup"); - if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, false) - ); + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup"); + if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, false) + ); - // 配置child节点信息 - int32_t childCount = flutterNode.childrenInTraversalOrder.size(); - if (childCount > 0) { - auto childrenIdsVec = flutterNode.childrenInTraversalOrder; - std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); - int64_t childNodeIds[childCount]; - for (int32_t i = 0; i < childCount; i++) { - childNodeIds[i] = static_cast(childrenIdsVec[i]); - FML_DLOG(INFO) - << "FlutterNodeToElementInfoById -> elementid=0 childCount=" - << childCount << " childNodeIds=" << childNodeIds[i]; - } - int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = - OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); - if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds) - ); + // 配置child节点信息 + int32_t childCount = flutterNode.childrenInTraversalOrder.size(); + if (childCount > 0) { + auto childrenIdsVec = flutterNode.childrenInTraversalOrder; + std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); + int64_t childNodeIds[childCount]; + for (int32_t i = 0; i < childCount; i++) { + childNodeIds[i] = static_cast(childrenIdsVec[i]); + FML_DLOG(INFO) + << "FlutterNodeToElementInfoById -> elementid=0 childCount=" + << childCount << " childNodeIds=" << childNodeIds[i]; } - - // 配置root节点常用属性 - int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); - if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); + int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = + OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); + if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true)); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds) + ); + } + + // 配置root节点常用属性 + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); + if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true)); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); - if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true)); + int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); + if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true)); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetFocusable"); - if (OH_ArkUI_AccessibilityElementInfoSetFocusable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetFocusable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true)); + int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetFocusable"); + if (OH_ArkUI_AccessibilityElementInfoSetFocusable == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetFocusable is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true)); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetVisible)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetVisible"); - if (OH_ArkUI_AccessibilityElementInfoSetVisible == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetVisible is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true)); + int32_t (*OH_ArkUI_AccessibilityElementInfoSetVisible)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetVisible"); + if (OH_ArkUI_AccessibilityElementInfoSetVisible == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetVisible is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true)); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = - OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetComponentType"); - if (OH_ArkUI_AccessibilityElementInfoSetComponentType == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetComponentType is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root")); + int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetComponentType"); + if (OH_ArkUI_AccessibilityElementInfoSetComponentType == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetComponentType is null, %{public}s", dlerror()); + } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root")); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetContents)(ArkUI_AccessibilityElementInfo*, const char*) = - OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetContents"); - if (OH_ArkUI_AccessibilityElementInfoSetContents == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetContents is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, flutterNode.label.c_str())); - } else { - //当elementId >= 1时,根据flutter节点信息配置elementinfo无障碍属性 - FlutterSetElementInfoProperties(elementInfoFromList, elementId); + int32_t (*OH_ArkUI_AccessibilityElementInfoSetContents)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetContents"); + if (OH_ArkUI_AccessibilityElementInfoSetContents == nullptr) { + LOGE("OH_ArkUI_AccessibilityElementInfoSetContents is null, %{public}s", dlerror()); } + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, flutterNode.label.c_str())); + } else { + //当elementId >= 1时,根据flutter节点信息配置elementinfo无障碍属性 + FlutterSetElementInfoProperties(elementInfoFromList, elementId); } - FML_DLOG(INFO) << "=== OhosAccessibilityBridge::FlutterNodeToElementInfoById is end ==="; -} -/** - * 判断源字符串是否包含目标字符串 - */ -bool OhosAccessibilityBridge::Contains(const std::string source, - const std::string target) -{ - return source.find(target) != std::string::npos; + FML_DLOG(INFO) << "=== OhosAccessibilityBridge::FlutterNodeToElementInfoById is end ==="; } /** @@ -968,8 +781,8 @@ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( if (OH_ArkUI_AccessibilityElementInfoSetOperationActions == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetOperationActions is null, %{public}s", dlerror()); } - if (Contains(widget_type, EDIT_TEXT_WIDGET_NAME) || - Contains(widget_type, EDIT_MULTILINE_TEXT_WIDGET_NAME)) { + if (OHOSUtils::Contains(widget_type, EDIT_TEXT_WIDGET_NAME) || + OHOSUtils::Contains(widget_type, EDIT_MULTILINE_TEXT_WIDGET_NAME)) { // set elementinfo action types int32_t actionTypeNum = 10; ArkUI_AccessibleAction actions[actionTypeNum]; @@ -1017,7 +830,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions) ); - } else if (Contains(widget_type, SCROLL_WIDGET_NAME)) { + } else if (OHOSUtils::Contains(widget_type, SCROLL_WIDGET_NAME)) { // if node is a scrollable component int32_t actionTypeNum = 5; ArkUI_AccessibleAction actions[actionTypeNum]; @@ -1095,7 +908,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( // 相对-绝对坐标映射 FlutterRelativeRectToScreenRect(flutterNode); auto [left, top, right, bottom] = GetAbsoluteScreenRect(flutterNode); - ArkUI_AccessibleRect rect = {static_cast(left), static_cast(top), + ArkUI_AccessibleRect rect = {static_cast(left), static_cast(top), static_cast(right), static_cast(bottom)}; int32_t (*OH_ArkUI_AccessibilityElementInfoSetScreenRect)(ArkUI_AccessibilityElementInfo*, ArkUI_AccessibleRect*) = OhosAccessibilityDDL::DLLoadSetElemSreenRectFunc("OH_ArkUI_AccessibilityElementInfoSetScreenRect"); @@ -1436,21 +1249,20 @@ void OhosAccessibilityBridge::BuildArkUISemanticsTree( int64_t elementInfoCount = levelOrderTreeVec.size(); //创建并配置节点id >= 1的全部节点 for (int64_t i = 1; i < elementInfoCount; i++) { - int64_t levelOrderId = levelOrderTreeVec[i]; - auto newNode = GetFlutterSemanticsNode(levelOrderId); - if (g_flutterSemanticsTree.count(newNode.id)) { - LOGE("BuildArkUISemanticsTree: GetFlutterSemanticsNode id=%{public}ld null", levelOrderId); - } - //当节点为隐藏状态时,自动规避 - ArkUI_AccessibilityElementInfo* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = - OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); - if (OH_ArkUI_AddAndGetAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_AddAndGetAccessibilityElementInfo is null, %{public}s", dlerror()); - } - ArkUI_AccessibilityElementInfo* newElementInfo = - OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); - //配置当前子节点信息 - FlutterNodeToElementInfoById(newElementInfo, levelOrderId); + int64_t levelOrderId = levelOrderTreeVec[i]; + auto newNode = GetFlutterSemanticsNode(levelOrderId); + if (g_flutterSemanticsTree.count(newNode.id)) { + LOGE("BuildArkUISemanticsTree: GetFlutterSemanticsNode id=%{public}ld null", levelOrderId); + } + //当节点为隐藏状态时,自动规避 + auto* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = + OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); + if (OH_ArkUI_AddAndGetAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_AddAndGetAccessibilityElementInfo is null, %{public}s", dlerror()); + } + auto* newElementInfo = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + //配置当前子节点信息 + FlutterNodeToElementInfoById(newElementInfo, levelOrderId); } } } @@ -1493,13 +1305,12 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( if (OH_GetSdkApiVersion() >= 13) { // 从elementinfolist中获取elementinfo - ArkUI_AccessibilityElementInfo* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = + auto* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); if (OH_ArkUI_AddAndGetAccessibilityElementInfo == nullptr) { LOGE("OH_ArkUI_AddAndGetAccessibilityElementInfo is null, %{public}s", dlerror()); } - ArkUI_AccessibilityElementInfo* elementInfoFromList = - OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + auto* elementInfoFromList = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); if (elementInfoFromList == nullptr) { FML_DLOG(INFO) << "FindAccessibilityNodeInfosById elementInfoFromList is null"; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; @@ -1543,9 +1354,9 @@ void OhosAccessibilityBridge::DispatchSemanticsAction( fml::MallocMapping args) { nativeAccessibilityChannel_->DispatchSemanticsAction(native_shell_holder_id_, - id, - action, - fml::MallocMapping()); + id, + action, + fml::MallocMapping()); } /** @@ -1555,7 +1366,6 @@ void OhosAccessibilityBridge::DoubleClickRouteToNewPage(SemanticsNodeExtent node { if (isFlutterSemanticsTreeUpdated && node.HasFlag(FLAGS_::kIsButton)) { RequestFocusWhenPageUpdate(0); - // isFlutterSemanticsTreeUpdated = false; } } @@ -1600,7 +1410,7 @@ void OhosAccessibilityBridge::PerformLongClickAction( * perform focus acquisition in accessibility status */ void OhosAccessibilityBridge::PerformGainFocusnAction( - int64_t elementId, + int64_t elementId, ArkUI_Accessibility_ActionType action, SemanticsNodeExtent flutterNode) { @@ -1620,7 +1430,8 @@ void OhosAccessibilityBridge::PerformGainFocusnAction( if (flutterNode.HasAction(ACTIONS_::kIncrease) || flutterNode.HasAction(ACTIONS_::kDecrease)) { Flutter_SendAccessibilityAsyncEvent( - elementId, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); + elementId, ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SELECTED); } } @@ -1649,7 +1460,7 @@ void OhosAccessibilityBridge::PerformClearFocusAction( * perform scroll forward in accessibility status */ void OhosAccessibilityBridge::PerformScrollUpAction( - int64_t elementId, + int64_t elementId, ArkUI_Accessibility_ActionType action, SemanticsNodeExtent flutterNode) { @@ -1668,14 +1479,14 @@ void OhosAccessibilityBridge::PerformScrollUpAction( DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kIncrease, {}); } std::string currComponetType = GetNodeComponentType(flutterNode); - if (Contains(currComponetType, SCROLL_WIDGET_NAME)) { - /** Scrolled event, sent when a scrollable component experiences a scroll event. 4096 */ - ArkUI_AccessibilityEventType scrollEventType1 = - ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; - Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); - FML_DLOG(INFO) - << "ExecuteAccessibilityAction -> action: scroll forward(" << action - << ")" << " event: scroll forward(" << scrollEventType1 << ")"; + if (OHOSUtils::Contains(currComponetType, SCROLL_WIDGET_NAME)) { + /** Scrolled event, sent when a scrollable component experiences a scroll event. 4096 */ + ArkUI_AccessibilityEventType scrollEventType1 = + ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_SCROLLED; + Flutter_SendAccessibilityAsyncEvent(elementId, scrollEventType1); + FML_DLOG(INFO) + << "ExecuteAccessibilityAction -> action: scroll forward(" << action + << ")" << " event: scroll forward(" << scrollEventType1 << ")"; } } @@ -1702,7 +1513,7 @@ void OhosAccessibilityBridge::PerformScrollDownAction( DispatchSemanticsAction(static_cast(elementId), ACTIONS_::kDecrease, {}); } std::string currComponetType = GetNodeComponentType(flutterNode); - if (Contains(currComponetType, SCROLL_WIDGET_NAME)) { + if (OHOSUtils::Contains(currComponetType, SCROLL_WIDGET_NAME)) { /** Scrolled event, sent when a scrollable component experiences a * scroll event. 4096 */ ArkUI_AccessibilityEventType scrollEventType1 = @@ -1756,7 +1567,7 @@ void OhosAccessibilityBridge::PerformSetText( ArkUI_AccessibilityActionArguments* actionArguments) { if (OH_GetSdkApiVersion() >= 13) { - int32_t (*OH_ArkUI_FindAccessibilityActionArgumentByKey)(ArkUI_AccessibilityActionArguments*, const char*, char**) = + int32_t (*OH_ArkUI_FindAccessibilityActionArgumentByKey)(ArkUI_AccessibilityActionArguments*, const char*, char**) = OhosAccessibilityDDL::DLLoadGetFindActionArgs("OH_ArkUI_FindAccessibilityActionArgumentByKey"); if (OH_ArkUI_FindAccessibilityActionArgumentByKey == nullptr) { LOGE("OH_ArkUI_FindAccessibilityActionArgumentByKey is null, %{public}s", dlerror()); @@ -2111,7 +1922,7 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( OH_ArkUI_SendAccessibilityAsyncEvent(provider_, eventInfo, callback); // 7.销毁新创建的elementinfo, eventinfo - void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = + void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); if (OH_ArkUI_DestoryAccessibilityElementInfo == nullptr) { LOGE("OH_ArkUI_DestoryAccessibilityElementInfo is null, %{public}s", dlerror()); @@ -2384,7 +2195,7 @@ std::string OhosAccessibilityBridge::GetRouteName(SemanticsNodeExtent node) return ""; } -void OhosAccessibilityBridge::onWindowNameChange(SemanticsNodeExtent route) +void OhosAccessibilityBridge::OnWindowNameChange(SemanticsNodeExtent route) { std::string routeName = GetRouteName(route); if (routeName.empty()) { @@ -2392,10 +2203,11 @@ void OhosAccessibilityBridge::onWindowNameChange(SemanticsNodeExtent route) } Flutter_SendAccessibilityAsyncEvent( static_cast(route.id), - ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_CONTENT_UPDATE); } -void OhosAccessibilityBridge::removeSemanticsNode( +void OhosAccessibilityBridge::RemoveSemanticsNode( SemanticsNodeExtent nodeToBeRemoved) { if (!g_flutterSemanticsTree.size()) { diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 08d196aee1..e8c78b71ca 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -26,6 +26,7 @@ #include "native_accessibility_channel.h" #include "ohos_accessibility_features.h" #include "ohos_accessibility_ddl.h" +#include "flutter/shell/platform/ohos/utils/ohos_utils.h" namespace flutter { typedef flutter::SemanticsFlags FLAGS_; @@ -83,7 +84,7 @@ public: void SetNativeShellHolderId(int64_t id); - void updateSemantics(flutter::SemanticsNodeUpdates update, + void UpdateSemantics(flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions); void DispatchSemanticsAction(int32_t id, @@ -231,8 +232,6 @@ private: void FlutterSetElementInfoOperationActions( ArkUI_AccessibilityElementInfo* elementInfoFromList, std::string widget_type); - void FlutterTreeToArkuiTree( - ArkUI_AccessibilityElementInfoList* elementInfoList); void BuildArkUISemanticsTree( int64_t elementId, ArkUI_AccessibilityElementInfo* elementInfoFromList, @@ -264,27 +263,27 @@ private: bool IsSlider(SemanticsNodeExtent flutterNode); bool IsScrollableWidget(SemanticsNodeExtent flutterNode); - void PerformClickAction(int64_t elementId, - ArkUI_Accessibility_ActionType action, + void PerformClickAction(int64_t elementId, + ArkUI_Accessibility_ActionType action, SemanticsNodeExtent flutterNode); - void PerformLongClickAction(int64_t elementId, - ArkUI_Accessibility_ActionType action, + void PerformLongClickAction(int64_t elementId, + ArkUI_Accessibility_ActionType action, SemanticsNodeExtent flutterNode); - void PerformGainFocusnAction(int64_t elementId, + void PerformGainFocusnAction(int64_t elementId, ArkUI_Accessibility_ActionType action, SemanticsNodeExtent flutterNode); - void PerformClearFocusAction(int64_t elementId, + void PerformClearFocusAction(int64_t elementId, ArkUI_Accessibility_ActionType action, SemanticsNodeExtent flutterNode); - void PerformScrollUpAction(int64_t elementId, + void PerformScrollUpAction(int64_t elementId, ArkUI_Accessibility_ActionType action, SemanticsNodeExtent flutterNode); - void PerformScrollDownAction(int64_t elementId, + void PerformScrollDownAction(int64_t elementId, ArkUI_Accessibility_ActionType action, SemanticsNodeExtent flutterNode); - void PerformClipboardAction(int64_t elementId, + void PerformClipboardAction(int64_t elementId, ArkUI_Accessibility_ActionType action); - void PerformInvalidAction(int64_t elementId, + void PerformInvalidAction(int64_t elementId, ArkUI_Accessibility_ActionType action, SemanticsNodeExtent flutterNode); void PerformSetText(SemanticsNodeExtent flutterNode, @@ -302,10 +301,10 @@ private: void PerformShowOnScreenAction(SemanticsNodeExtent flutterNode); void AddRouteNodes(std::vector edges, - SemanticsNodeExtent node); + SemanticsNodeExtent node); std::string GetRouteName(SemanticsNodeExtent node); - void onWindowNameChange(SemanticsNodeExtent route); - void removeSemanticsNode(SemanticsNodeExtent nodeToBeRemoved); + void OnWindowNameChange(SemanticsNodeExtent route); + void RemoveSemanticsNode(SemanticsNodeExtent nodeToBeRemoved); void GetSemanticsNodeDebugInfo(SemanticsNodeExtent node); void GetSemanticsFlagsDebugInfo(SemanticsNodeExtent node); diff --git a/shell/platform/ohos/utils/ohos_utils.cpp b/shell/platform/ohos/utils/ohos_utils.cpp index d56f8f579e..fd4b68f7e6 100644 --- a/shell/platform/ohos/utils/ohos_utils.cpp +++ b/shell/platform/ohos/utils/ohos_utils.cpp @@ -13,11 +13,18 @@ * limitations under the License. */ #include "ohos_utils.h" - namespace flutter { OHOSUtils::OHOSUtils() {}; OHOSUtils::~OHOSUtils() {}; +/** + * 判断源字符串是否包含目标字符串 + */ +bool OHOSUtils::Contains(const std::string source, + const std::string target) +{ + return source.find(target) != std::string::npos; +} } \ No newline at end of file diff --git a/shell/platform/ohos/utils/ohos_utils.h b/shell/platform/ohos/utils/ohos_utils.h index 938cb07906..802d6f306a 100644 --- a/shell/platform/ohos/utils/ohos_utils.h +++ b/shell/platform/ohos/utils/ohos_utils.h @@ -15,6 +15,7 @@ #ifndef OHOS_UTILS_H #define OHOS_UTILS_H +#include namespace flutter { @@ -22,7 +23,8 @@ class OHOSUtils { public: OHOSUtils(); ~OHOSUtils(); - + + static bool Contains(const std::string source, const std::string target); }; } -- Gitee From d8b31045afbfb622b63d8ef32ca8377b99e587b3 Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 16 Dec 2024 16:55:06 +0800 Subject: [PATCH 08/15] =?UTF-8?q?=E9=87=8D=E6=9E=84=E9=83=A8=E5=88=86?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8C=E5=AE=8C=E5=96=84=E9=9D=99=E6=80=81?= =?UTF-8?q?=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 215 +++++++++--------- .../accessibility/ohos_accessibility_bridge.h | 8 +- .../flutter_embedding/build-profile.json5 | 16 +- .../ohos/napi/platform_view_ohos_napi.cpp | 14 +- .../ohos/napi/platform_view_ohos_napi.h | 1 + shell/platform/ohos/utils/ohos_utils.cpp | 2 +- shell/platform/ohos/utils/ohos_utils.h | 4 +- 7 files changed, 145 insertions(+), 115 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 8fd91391fd..1224d30d56 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -41,6 +41,8 @@ namespace flutter { +const int32_t OhosAccessibilityBridge::OHOS_API_VERSION = OH_GetSdkApiVersion(); + OhosAccessibilityBridge* OhosAccessibilityBridge::bridgeInstance = nullptr; OhosAccessibilityBridge* OhosAccessibilityBridge::GetInstance() @@ -96,44 +98,46 @@ void OhosAccessibilityBridge::UpdateSemantics( // 当flutter页面状态更新(路由新页面)时,自动请求root节点组件获焦(规避滑动组件更新干扰) if (IS_FLUTTER_NAVIGATE) { - Flutter_SendAccessibilityAsyncEvent(0, ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_STATE_UPDATE); + Flutter_SendAccessibilityAsyncEvent(0, + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_PAGE_STATE_UPDATE); RequestFocusWhenPageUpdate(0); IS_FLUTTER_NAVIGATE = false; } /** 获取并分析每个语义节点的更新属性 */ for (auto& item : update) { - // 获取当前更新的节点node - const auto& node = item.second; - - // 更新扩展的SemanticsNode信息 - auto nodeEx = UpdatetSemanticsNodeExtent(node); - - //print semantics node and flags info for debugging - GetSemanticsNodeDebugInfo(nodeEx); - GetSemanticsFlagsDebugInfo(nodeEx); - - /** - * 构建flutter无障碍语义节点树 - * NOTE: 若使用g_flutterSemanticsTree.insert({node.id, node})方式 - * 来添加新增的语义节点会导致已有key值自动忽略,不会更新原有key对应的value - */ - g_flutterSemanticsTree[nodeEx.id] = nodeEx; - - // 若当前节点为获焦 - if (IsNodeFocused(nodeEx)) { - inputFocusedNode = nodeEx; - } - // 若当前节点和更新前节点信息不同,则加入更新节点数组 - if (nodeEx.hadPreviousConfig) { - updatedFlutterNodes.emplace_back(nodeEx); - } + // 获取当前更新的节点node + const auto& node = item.second; - // 获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 - int32_t childNodeCount = nodeEx.childrenInTraversalOrder.size(); - for (int32_t i = 0; i < childNodeCount; i++) { - g_parentChildIdVec.emplace_back(std::make_pair(nodeEx.id, nodeEx.childrenInTraversalOrder[i])); - } + // 更新扩展的SemanticsNode信息 + auto nodeEx = UpdatetSemanticsNodeExtent(node); + + //print semantics node and flags info for debugging + GetSemanticsNodeDebugInfo(nodeEx); + GetSemanticsFlagsDebugInfo(nodeEx); + + /** + * 构建flutter无障碍语义节点树 + * NOTE: 若使用g_flutterSemanticsTree.insert({node.id, node})方式 + * 来添加新增的语义节点会导致已有key值自动忽略,不会更新原有key对应的value + */ + g_flutterSemanticsTree[nodeEx.id] = nodeEx; + + // 若当前节点为获焦 + if (IsNodeFocused(nodeEx)) { + inputFocusedNode = nodeEx; + } + // 若当前节点和更新前节点信息不同,则加入更新节点数组 + if (nodeEx.hadPreviousConfig) { + updatedFlutterNodes.emplace_back(nodeEx); + } + + // 获取当前flutter节点的全部子节点数量,并构建父子节点id映射关系 + int32_t childNodeCount = nodeEx.childrenInTraversalOrder.size(); + for (int32_t i = 0; i < childNodeCount; i++) { + g_parentChildIdVec.emplace_back(std::make_pair(nodeEx.id, nodeEx.childrenInTraversalOrder[i])); + } } // 页面内容更新事件 @@ -147,31 +151,29 @@ void OhosAccessibilityBridge::UpdateSemantics( // 当滑动节点产生滑动,并执行滑动处理 if (HasScrolled(nodeEx)) { LOGD("UpdateSemantics -> has scrolled"); - if (OH_GetSdkApiVersion() >= 13) { - ArkUI_AccessibilityElementInfo* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = - OhosAccessibilityDDL::DLLoadCreateElemInfoFunc("OH_ArkUI_CreateAccessibilityElementInfo"); - if (OH_ArkUI_CreateAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_CreateAccessibilityElementInfo is null, %{public}s", dlerror()); - } - ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); + ArkUI_AccessibilityElementInfo* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = + OhosAccessibilityDDL::DLLoadCreateElemInfoFunc("OH_ArkUI_CreateAccessibilityElementInfo"); + if (OH_ArkUI_CreateAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_CreateAccessibilityElementInfo is null, %{public}s", dlerror()); + } + ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); - FlutterNodeToElementInfoById(_elementInfo, static_cast(nodeEx.id)); - // flutter滑动组件滑动处理逻辑 - FlutterScrollExecution(nodeEx, _elementInfo); + FlutterNodeToElementInfoById(_elementInfo, static_cast(nodeEx.id)); + // flutter滑动组件滑动处理逻辑 + FlutterScrollExecution(nodeEx, _elementInfo); - // 屏幕朗读状态下双指滑动,获焦节点绿框实时跟随节点滑动 - Flutter_SendAccessibilityAsyncEvent( - static_cast(accessibilityFocusedNode.id), - ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_FOCUS_NODE_UPDATE); + // 屏幕朗读状态下双指滑动,获焦节点绿框实时跟随节点滑动 + Flutter_SendAccessibilityAsyncEvent( + static_cast(accessibilityFocusedNode.id), + ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_FOCUS_NODE_UPDATE); - void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = - OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); - if (OH_ArkUI_DestoryAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_DestoryAccessibilityElementInfo is null, %{public}s", dlerror()); - } - OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); - _elementInfo = nullptr; + void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = + OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); + if (OH_ArkUI_DestoryAccessibilityElementInfo == nullptr) { + LOGE("OH_ArkUI_DestoryAccessibilityElementInfo is null, %{public}s", dlerror()); } + OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); + _elementInfo = nullptr; } // 判断是否触发liveRegion活动区,当前节点是否活跃 @@ -196,7 +198,7 @@ void OhosAccessibilityBridge::FlutterScrollExecution( SemanticsNodeExtent node, ArkUI_AccessibilityElementInfo* elementInfoFromList) { - if (OH_GetSdkApiVersion() >= 13) { + if (OHOS_API_VERSION >= 13) { double nodePosition = node.scrollPosition; double nodeScrollExtentMax = node.scrollExtentMax; double nodeScrollExtentMin = node.scrollExtentMin; @@ -236,7 +238,8 @@ void OhosAccessibilityBridge::FlutterScrollExecution( if (OH_ArkUI_AccessibilityElementInfoSetItemCount == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetItemCount is null, %{public}s", dlerror()); } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetItemCount(elementInfoFromList, itemCount)); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetItemCount(elementInfoFromList, itemCount)); // 设置当前页面可见的起始滑动index int32_t startItemIndex = node.scrollIndex; @@ -245,7 +248,8 @@ void OhosAccessibilityBridge::FlutterScrollExecution( if (OH_ArkUI_AccessibilityElementInfoSetStartItemIndex == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetStartItemIndex is null, %{public}s", dlerror()); } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, startItemIndex)); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, startItemIndex)); // 设置当前获焦节点的当前index int32_t currItemIndex = accessibilityFocusedNode.id; @@ -254,7 +258,8 @@ void OhosAccessibilityBridge::FlutterScrollExecution( if (OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex is null, %{public}s", dlerror()); } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex(elementInfoFromList, currItemIndex)); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex(elementInfoFromList, currItemIndex)); // 计算当前滑动位置页面的可见子滑动节点数量 int visibleChildren = 0; @@ -299,7 +304,7 @@ void OhosAccessibilityBridge::RequestFocusWhenPageUpdate(int32_t requestFocusId) "AccessibilityProvider = nullptr"; return; } - if (OH_GetSdkApiVersion() >= 13) { + if (OHOS_API_VERSION >= 13) { ArkUI_AccessibilityEventInfo* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); if (OH_ArkUI_CreateAccessibilityEventInfo == nullptr) { @@ -384,7 +389,7 @@ void OhosAccessibilityBridge::Announce(std::unique_ptr& message) "AccessibilityProvider = nullptr"; return; } - if (OH_GetSdkApiVersion() >= 13) { + if (OHOS_API_VERSION >= 13) { // 创建并设置屏幕朗读事件 ArkUI_AccessibilityEventInfo* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); @@ -536,7 +541,7 @@ void OhosAccessibilityBridge::FlutterRelativeRectToScreenRect( auto currRight = static_cast(currNode.rect.fRight); auto currBottom = static_cast(currNode.rect.fBottom); - /** + /** * 获取当前flutter节点的缩放、平移、透视等矩阵坐标转换 * 以下矩阵坐标变换参数(如:旋转/错切、透视)场景目前暂不考虑 * NOTE: SkMatrix::kMSkewX, SkMatrix::kMSkewY, @@ -552,7 +557,7 @@ void OhosAccessibilityBridge::FlutterRelativeRectToScreenRect( int32_t parentId = GetParentId(currNode.id); auto parentNode = GetFlutterSemanticsNode(parentId); if (!g_flutterSemanticsTree.count(parentId)) { - LOGE("FlutterRelativeRectToScreenRect: GetFlutterSemanticsNode id=%{public}d null", parentId); + LOGE("FlutterRelativeRectToScreenRect: GetFlutterSemanticsNode id=%{public}d null", parentId); } // 获取当前flutter节点的父节点的绝对坐标 @@ -560,9 +565,9 @@ void OhosAccessibilityBridge::FlutterRelativeRectToScreenRect( //获取root节点的绝对坐标 auto rootNode = GetFlutterSemanticsNode(0); - auto _rootRect = GetAbsoluteScreenRect(rootNode); - auto rootWidth = _rootRect.right; - auto rootHeight = _rootRect.bottom; + auto rootRect = GetAbsoluteScreenRect(rootNode); + auto rootWidth = rootRect.right; + auto rootHeight = rootRect.bottom; // 获取真实缩放系数 auto [realScaleXFactor, realScaleYFactor] = GetRealScaleFactor(); @@ -649,7 +654,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( FlutterSetElementInfoOperationActions(elementInfoFromList, OTHER_WIDGET_NAME); // 根据flutternode信息配置对应的elementinfo - int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetElementId"); if (OH_ArkUI_AccessibilityElementInfoSetElementId == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetElementId is null, %{public}s", dlerror()); @@ -657,7 +662,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, 0)); // NOTE: arkui无障碍子系统强制设置root的父节点id = -2100000 (严禁更改) - int32_t (*OH_ArkUI_AccessibilityElementInfoSetParentId)(ArkUI_AccessibilityElementInfo*, int32_t) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetParentId)(ArkUI_AccessibilityElementInfo*, int32_t) = OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetParentId"); if (OH_ArkUI_AccessibilityElementInfoSetParentId == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetParentId is null, %{public}s", dlerror()); @@ -667,18 +672,18 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( ); // 设置无障碍播报文本 - int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityText)(ArkUI_AccessibilityElementInfo*, const char*) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityText)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText"); if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityText == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText is null, %{public}s", dlerror()); } ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( - elementInfoFromList, flutterNode.label.empty() ? + elementInfoFromList, flutterNode.label.empty() ? flutterNode.value.c_str() : flutterNode.label.c_str()) ); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel)(ArkUI_AccessibilityElementInfo*, const char*) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel"); if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel is null, %{public}s", dlerror()); @@ -687,7 +692,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes") ); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup)(ArkUI_AccessibilityElementInfo*, bool) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup"); if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup is null, %{public}s", dlerror()); @@ -719,42 +724,42 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( } // 配置root节点常用属性 - int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); } ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true)); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); } ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true)); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetFocusable"); if (OH_ArkUI_AccessibilityElementInfoSetFocusable == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetFocusable is null, %{public}s", dlerror()); } ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true)); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetVisible)(ArkUI_AccessibilityElementInfo*, bool) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetVisible)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetVisible"); if (OH_ArkUI_AccessibilityElementInfoSetVisible == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetVisible is null, %{public}s", dlerror()); } ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true)); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetComponentType"); if (OH_ArkUI_AccessibilityElementInfoSetComponentType == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetComponentType is null, %{public}s", dlerror()); } ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root")); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetContents)(ArkUI_AccessibilityElementInfo*, const char*) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetContents)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetContents"); if (OH_ArkUI_AccessibilityElementInfoSetContents == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetContents is null, %{public}s", dlerror()); @@ -775,7 +780,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( ArkUI_AccessibilityElementInfo* elementInfoFromList, std::string widget_type) { - if (OH_GetSdkApiVersion() >= 13) { + if (OHOS_API_VERSION >= 13) { int32_t (*OH_ArkUI_AccessibilityElementInfoSetOperationActions)(ArkUI_AccessibilityElementInfo*, int32_t, ArkUI_AccessibleAction*) = OhosAccessibilityDDL::DLLoadSetElemOperActionsFunc("OH_ArkUI_AccessibilityElementInfoSetOperationActions"); if (OH_ArkUI_AccessibilityElementInfoSetOperationActions == nullptr) { @@ -889,14 +894,14 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId) { - if (OH_GetSdkApiVersion() >= 13) { + if (OHOS_API_VERSION >= 13) { SemanticsNodeExtent flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); if (flutterNode.isNull) { LOGE("FlutterSetElementInfoProperties: GetFlutterSemanticsNode id=%{public}ld null", elementId); } // set elementinfo id - int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetElementId"); if (OH_ArkUI_AccessibilityElementInfoSetElementId == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetElementId is null, %{public}s", dlerror()); @@ -925,7 +930,8 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( // 配置arkui的elementinfo可操作动作属性 if (IsTextField(flutterNode)) { // 若当前flutter节点为文本输入框组件 - std::string widgeType = flutterNode.HasFlag(FLAGS_::kIsMultiline) ? EDIT_MULTILINE_TEXT_WIDGET_NAME : EDIT_TEXT_WIDGET_NAME; + std::string widgeType = flutterNode.HasFlag(FLAGS_::kIsMultiline) ? + EDIT_MULTILINE_TEXT_WIDGET_NAME : EDIT_TEXT_WIDGET_NAME; FlutterSetElementInfoOperationActions(elementInfoFromList, widgeType); } else if (IsScrollableWidget(flutterNode) || IsNodeScrollable(flutterNode)) { // 若当前flutter节点为可滑动组件类型 @@ -991,7 +997,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( << " childCount=" << childCount << " childNodeIds=" << childNodeIds[i]; } - int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); @@ -1157,7 +1163,7 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( FML_DLOG(INFO) << "FlutterNodeToElementInfoById componentTypeName = " << componentTypeName; // flutter节点对应elementinfo所属的组件类型(如:root, button,text等) - int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetComponentType"); if (OH_ArkUI_AccessibilityElementInfoSetComponentType == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetComponentType is null, %{public}s", dlerror()); @@ -1241,7 +1247,7 @@ void OhosAccessibilityBridge::BuildArkUISemanticsTree( ArkUI_AccessibilityElementInfo* elementInfoFromList, ArkUI_AccessibilityElementInfoList* elementList) { - if (OH_GetSdkApiVersion() >= 13) { + if (OHOS_API_VERSION >= 13) { //配置root节点信息 FlutterNodeToElementInfoById(elementInfoFromList, elementId); //获取flutter无障碍语义树的节点总数 @@ -1303,7 +1309,7 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( accessibilityFeatures_->SetAccessibleNavigation(true, native_shell_holder_id_); } - if (OH_GetSdkApiVersion() >= 13) { + if (OHOS_API_VERSION >= 13) { // 从elementinfolist中获取elementinfo auto* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); @@ -1373,7 +1379,7 @@ void OhosAccessibilityBridge::DoubleClickRouteToNewPage(SemanticsNodeExtent node * perform click action in accessibility status */ void OhosAccessibilityBridge::PerformClickAction( - int64_t elementId, + int64_t elementId, ArkUI_Accessibility_ActionType action, SemanticsNodeExtent flutterNode) { @@ -1392,7 +1398,7 @@ void OhosAccessibilityBridge::PerformClickAction( * perform long-press action in accessibility status */ void OhosAccessibilityBridge::PerformLongClickAction( - int64_t elementId, + int64_t elementId, ArkUI_Accessibility_ActionType action, SemanticsNodeExtent flutterNode) { @@ -1439,7 +1445,7 @@ void OhosAccessibilityBridge::PerformGainFocusnAction( * perform focus clearance in accessibility status */ void OhosAccessibilityBridge::PerformClearFocusAction( - int64_t elementId, + int64_t elementId, ArkUI_Accessibility_ActionType action, SemanticsNodeExtent flutterNode) { @@ -1528,7 +1534,7 @@ void OhosAccessibilityBridge::PerformScrollDownAction( * perform invalid action in accessibility status */ void OhosAccessibilityBridge::PerformClipboardAction( - int64_t elementId, + int64_t elementId, ArkUI_Accessibility_ActionType action) { if (action == ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY) { @@ -1546,7 +1552,7 @@ void OhosAccessibilityBridge::PerformClipboardAction( * perform invalid action in accessibility status */ void OhosAccessibilityBridge::PerformInvalidAction( - int64_t elementId, + int64_t elementId, ArkUI_Accessibility_ActionType action, SemanticsNodeExtent flutterNode) { @@ -1566,22 +1572,25 @@ void OhosAccessibilityBridge::PerformSetText( ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments) { - if (OH_GetSdkApiVersion() >= 13) { + if (OHOS_API_VERSION >= 13) { int32_t (*OH_ArkUI_FindAccessibilityActionArgumentByKey)(ArkUI_AccessibilityActionArguments*, const char*, char**) = OhosAccessibilityDDL::DLLoadGetFindActionArgs("OH_ArkUI_FindAccessibilityActionArgumentByKey"); if (OH_ArkUI_FindAccessibilityActionArgumentByKey == nullptr) { - LOGE("OH_ArkUI_FindAccessibilityActionArgumentByKey is null, %{public}s", dlerror()); + LOGE("OH_ArkUI_FindAccessibilityActionArgumentByKey is null, %{public}s", dlerror()); } const char* key_setText = "setText"; const char* valueStr = flutterNode.value.c_str(); char* newValue = strdup(valueStr); char** value = &newValue; - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key_setText, value)); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key_setText, value)); if (newValue == nullptr) { LOGE("PerformSetText -> OH_ArkUI_FindAccessibilityActionArgumentByKey get null value"); } auto flutterSetTextAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(flutterNode.id, flutterSetTextAction, fml::MallocMapping::Copy(newValue, strlen(newValue))); + DispatchSemanticsAction(flutterNode.id, + flutterSetTextAction, + fml::MallocMapping::Copy(newValue, strlen(newValue))); flutterNode.value = newValue; flutterNode.valueAttributes = {}; LOGI("ExecuteAccessibilityAction -> action: set text(%{public}d), newText=%{public}s", action, newValue); @@ -1855,7 +1864,7 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( "AccessibilityProvider = nullptr"; return; } - if (OH_GetSdkApiVersion() >= 13) { + if (OHOS_API_VERSION >= 13) { // 1.创建eventInfo对象 ArkUI_AccessibilityEventInfo* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); @@ -1870,7 +1879,7 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( } // 2.创建的elementinfo并根据对应id的flutternode进行属性初始化 - ArkUI_AccessibilityElementInfo* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = + ArkUI_AccessibilityElementInfo* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = OhosAccessibilityDDL::DLLoadCreateElemInfoFunc("OH_ArkUI_CreateAccessibilityElementInfo"); if (OH_ArkUI_CreateAccessibilityElementInfo == nullptr) { LOGE("OH_ArkUI_CreateAccessibilityElementInfo is null, %{public}s", dlerror()); @@ -1879,7 +1888,7 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( FlutterNodeToElementInfoById(_elementInfo, elementId); // 若为获焦事件,则设置当前elementinfo获焦 - int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused)(ArkUI_AccessibilityElementInfo*, bool) = + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused"); if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused == nullptr) { LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused is null, %{public}s", dlerror()); @@ -1891,7 +1900,7 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( } // 3.设置发送事件,如配置获焦、失焦、点击、滑动事件 - int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = + int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = OhosAccessibilityDDL::DLLoadSetEventFunc("OH_ArkUI_AccessibilityEventSetEventType"); if (OH_ArkUI_AccessibilityEventSetEventType == nullptr) { LOGE("OH_ArkUI_AccessibilityEventSetEventType is null, %{public}s", dlerror()); @@ -1899,7 +1908,7 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityEventSetEventType(eventInfo, eventType)); // 4.将eventinfo事件和当前elementinfo进行绑定 - int32_t (*OH_ArkUI_AccessibilityEventSetElementInfo)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityElementInfo*) = + int32_t (*OH_ArkUI_AccessibilityEventSetElementInfo)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityElementInfo*) = OhosAccessibilityDDL::DLLoadSetEventElemFunc("OH_ArkUI_AccessibilityEventSetElementInfo"); if (OH_ArkUI_AccessibilityEventSetElementInfo == nullptr) { LOGE("OH_ArkUI_AccessibilityEventSetElementInfo is null, %{public}s", dlerror()); @@ -1914,7 +1923,7 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( }; // 6.发送event到OH侧 - void (*OH_ArkUI_SendAccessibilityAsyncEvent)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*callback)(int32_t)) = + void (*OH_ArkUI_SendAccessibilityAsyncEvent)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*callback)(int32_t)) = OhosAccessibilityDDL::DLLoadSendAsyncEventFunc("OH_ArkUI_SendAccessibilityAsyncEvent"); if (OH_ArkUI_SendAccessibilityAsyncEvent == nullptr) { LOGE("OH_ArkUI_SendAccessibilityAsyncEvent is null, %{public}s", dlerror()); @@ -1930,7 +1939,7 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); _elementInfo = nullptr; - void (*OH_ArkUI_DestoryAccessibilityEventInfo)(ArkUI_AccessibilityEventInfo*) = + void (*OH_ArkUI_DestoryAccessibilityEventInfo)(ArkUI_AccessibilityEventInfo*) = OhosAccessibilityDDL::DLLoadDestroyEventFunc("OH_ArkUI_DestoryAccessibilityEventInfo"); if (OH_ArkUI_DestoryAccessibilityEventInfo == nullptr) { LOGE("OH_ArkUI_DestoryAccessibilityEventInfo is null, %{public}s", dlerror()); @@ -1969,7 +1978,7 @@ std::string OhosAccessibilityBridge::GetNodeComponentType( return HEADER_WIDGET_NAME; } if (node.HasFlag(FLAGS_::kIsImage)) { - return IMAGE_WIDGET_NAME; + return IMAGE_WIDGET_NAME; } if (node.HasFlag(FLAGS_::kHasCheckedState)) { if (node.HasFlag(FLAGS_::kIsInMutuallyExclusiveGroup)) { @@ -2087,7 +2096,7 @@ bool OhosAccessibilityBridge::IsNodeEnabled( */ bool OhosAccessibilityBridge::IsNodeShowOnScreen(SemanticsNodeExtent flutterNode) { - return flutterNode.HasAction(ACTIONS_::kShowOnScreen); + return flutterNode.HasAction(ACTIONS_::kShowOnScreen); } /** * 判断当前节点是否已经滑动 @@ -2107,7 +2116,7 @@ bool OhosAccessibilityBridge::HasChangedLabel(const SemanticsNodeExtent& flutter if (flutterNode.label.empty() && flutterNode.previousLabel.empty()) { return false; } - return flutterNode.label.empty() || + return flutterNode.label.empty() || flutterNode.previousLabel.empty() || flutterNode.label != flutterNode.previousLabel; } @@ -2223,7 +2232,7 @@ void OhosAccessibilityBridge::RemoveSemanticsNode( for (auto it = g_parentChildIdVec.begin(); it != g_parentChildIdVec.end(); it++) { if (it->first == nodeToBeRemovedParentId && it->second == nodeToBeRemoved.id) { - g_parentChildIdVec.erase(it); + g_parentChildIdVec.erase(it); } } } diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index e8c78b71ca..39d14c80eb 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -56,10 +56,12 @@ struct SemanticsNodeExtent : flutter::SemanticsNode { double previousScrollExtentMin = std::nan(""); std::string previousValue; std::string previousLabel; - bool HasPrevAction(SemanticsAction action) const { + bool HasPrevAction(SemanticsAction action) const + { return (previousActions & this->actions) != 0; } - bool HasPrevFlag(SemanticsFlags flag) const { + bool HasPrevFlag(SemanticsFlags flag) const + { return (previousFlags & this->flags) != 0; } }; @@ -166,7 +168,7 @@ private: SemanticsNodeExtent lastInputFocusedNode; SemanticsNodeExtent accessibilityFocusedNode; - // arkui的root节点的父节点id + static const int32_t OHOS_API_VERSION; static const int32_t ARKUI_ACCESSIBILITY_ROOT_PARENT_ID = -2100000; static const int32_t RET_ERROR_STATE_CODE = -1; static const int32_t ROOT_NODE_ID = 0; diff --git a/shell/platform/ohos/flutter_embedding/build-profile.json5 b/shell/platform/ohos/flutter_embedding/build-profile.json5 index c4150bb5a3..5e149a729c 100755 --- a/shell/platform/ohos/flutter_embedding/build-profile.json5 +++ b/shell/platform/ohos/flutter_embedding/build-profile.json5 @@ -15,7 +15,21 @@ { "app": { - "signingConfigs": [], + "signingConfigs": [ + { + "name": "default", + "type": "HarmonyOS", + "material": { + "certpath": "/Users/zijunxi/.ohos/config/default_flutter_embedding_rLTIk1jnFi1EHzVwrHLRwd24RS6fY4RPUwPq20ZOPzE=.cer", + "storePassword": "0000001B08FA11B2A4DAA98102847DAFB98304F1AC13B13A6B8F79579BEAF52F6A1D5D4DB74E2647047F9B", + "keyAlias": "debugKey", + "keyPassword": "0000001BF3FB1B423C45C8C2E02B8384FCD4271C32DC52C9B957E68D247C420B785F45D26558EB30EBD53D", + "profile": "/Users/zijunxi/.ohos/config/default_flutter_embedding_rLTIk1jnFi1EHzVwrHLRwd24RS6fY4RPUwPq20ZOPzE=.p7b", + "signAlg": "SHA256withECDSA", + "storeFile": "/Users/zijunxi/.ohos/config/default_flutter_embedding_rLTIk1jnFi1EHzVwrHLRwd24RS6fY4RPUwPq20ZOPzE=.p12" + } + } + ], "products": [ { "name": "default", diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index ef196b0b6c..431ff15b31 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -1871,8 +1871,11 @@ napi_value PlatformViewOHOSNapi::nativeAccessibilityStateChange( (state ? "true" : "false")); //send to accessibility bridge - auto a11y_bridge = OhosAccessibilityBridge::GetInstance(); - a11y_bridge->OnOhosAccessibilityStateChange(shell_holder_id, state); + const int32_t OHOS_API_VERSION = OH_GetSdkApiVersion(); + if (OHOS_API_VERSION >= 13) { + 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; @@ -1893,8 +1896,11 @@ 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 handler = std::make_shared(); - handler->Announce(char_array); + const int32_t OHOS_API_VERSION = OH_GetSdkApiVersion(); + if (OHOS_API_VERSION >= 13) { + auto handler = std::make_shared(); + handler->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 34be921e97..b246ad75c0 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.h +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -16,6 +16,7 @@ #ifndef PLATFORM_VIEW_OHOS_NAPI_H #define PLATFORM_VIEW_OHOS_NAPI_H #include +#include #include "flutter/assets/directory_asset_bundle.h" #include "flutter/common/settings.h" #include "flutter/fml/file.h" diff --git a/shell/platform/ohos/utils/ohos_utils.cpp b/shell/platform/ohos/utils/ohos_utils.cpp index fd4b68f7e6..23813a7528 100644 --- a/shell/platform/ohos/utils/ohos_utils.cpp +++ b/shell/platform/ohos/utils/ohos_utils.cpp @@ -22,7 +22,7 @@ OHOSUtils::~OHOSUtils() {}; * 判断源字符串是否包含目标字符串 */ bool OHOSUtils::Contains(const std::string source, - const std::string target) + const std::string target) { return source.find(target) != std::string::npos; } diff --git a/shell/platform/ohos/utils/ohos_utils.h b/shell/platform/ohos/utils/ohos_utils.h index 802d6f306a..f76e79bef3 100644 --- a/shell/platform/ohos/utils/ohos_utils.h +++ b/shell/platform/ohos/utils/ohos_utils.h @@ -28,6 +28,4 @@ public: }; } - - -#endif +#endif -- Gitee From 106c56ff79f2daa13130257ac89e238bfe47c861 Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 16 Dec 2024 17:57:24 +0800 Subject: [PATCH 09/15] =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=AD=BE=E5=90=8D?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos/flutter_embedding/build-profile.json5 | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/shell/platform/ohos/flutter_embedding/build-profile.json5 b/shell/platform/ohos/flutter_embedding/build-profile.json5 index 5e149a729c..c4150bb5a3 100755 --- a/shell/platform/ohos/flutter_embedding/build-profile.json5 +++ b/shell/platform/ohos/flutter_embedding/build-profile.json5 @@ -15,21 +15,7 @@ { "app": { - "signingConfigs": [ - { - "name": "default", - "type": "HarmonyOS", - "material": { - "certpath": "/Users/zijunxi/.ohos/config/default_flutter_embedding_rLTIk1jnFi1EHzVwrHLRwd24RS6fY4RPUwPq20ZOPzE=.cer", - "storePassword": "0000001B08FA11B2A4DAA98102847DAFB98304F1AC13B13A6B8F79579BEAF52F6A1D5D4DB74E2647047F9B", - "keyAlias": "debugKey", - "keyPassword": "0000001BF3FB1B423C45C8C2E02B8384FCD4271C32DC52C9B957E68D247C420B785F45D26558EB30EBD53D", - "profile": "/Users/zijunxi/.ohos/config/default_flutter_embedding_rLTIk1jnFi1EHzVwrHLRwd24RS6fY4RPUwPq20ZOPzE=.p7b", - "signAlg": "SHA256withECDSA", - "storeFile": "/Users/zijunxi/.ohos/config/default_flutter_embedding_rLTIk1jnFi1EHzVwrHLRwd24RS6fY4RPUwPq20ZOPzE=.p12" - } - } - ], + "signingConfigs": [], "products": [ { "name": "default", -- Gitee From 0334924ef01b14aff09dabefc880897d658eb90e Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 16 Dec 2024 19:17:25 +0800 Subject: [PATCH 10/15] =?UTF-8?q?=E5=A2=9E=E5=8A=A0unittests=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=9A=84build.gn=E7=9A=84deviceinfo=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E5=BA=93=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- shell/platform/ohos/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn index 982c45eab5..7dd1671fa5 100644 --- a/shell/platform/ohos/BUILD.gn +++ b/shell/platform/ohos/BUILD.gn @@ -249,6 +249,7 @@ executable("flutter_ohos_unittests") { ldflags += ["-lnative_window"] ldflags += ["-lnative_vsync"] ldflags += ["-limage_ndk.z"] + ldflags += ["-ldeviceinfo_ndk.z"] ldflags += ["-lrawfile.z"] ldflags += ["-lnative_image"] ldflags += ["-lpixelmap_ndk.z"] -- Gitee From f49b777a67bbd275b6100b17ba0276e71d3b4be0 Mon Sep 17 00:00:00 2001 From: zjxi Date: Mon, 16 Dec 2024 20:32:44 +0800 Subject: [PATCH 11/15] =?UTF-8?q?=E5=9B=9E=E9=80=80skia.patch=E7=89=88?= =?UTF-8?q?=E6=9C=AC=EF=BC=8C=E5=B9=B6=E5=A2=9E=E9=87=8F=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=AD=97=E9=87=8D=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- attachment/repos/skia.patch | 200 ++++++++++++++++++++++++------------ 1 file changed, 133 insertions(+), 67 deletions(-) diff --git a/attachment/repos/skia.patch b/attachment/repos/skia.patch index d85176705f..d4edec37a9 100644 --- a/attachment/repos/skia.patch +++ b/attachment/repos/skia.patch @@ -1,5 +1,5 @@ diff --git a/BUILD.gn b/BUILD.gn -index ebbd898ec9..2d4257e8d7 100644 +index ebbd898ec9..015bb75414 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -26,16 +26,21 @@ import("gn/ios.gni") @@ -7,7 +7,7 @@ index ebbd898ec9..2d4257e8d7 100644 # Skia public API, generally provided by :skia. config("skia_public") { - include_dirs = [ "." ] -+ include_dirs = [ ".", ++ include_dirs = [ ".", + "//third_part/khronos/", ] defines = [] @@ -142,16 +142,22 @@ index ebbd898ec9..2d4257e8d7 100644 ] if (!skia_enable_winuwp) { -@@ -1559,7 +1612,7 @@ skia_component("skia") { - ] +@@ -1566,6 +1619,14 @@ skia_component("skia") { + } } -- if (is_linux || is_wasm) { -+ if (is_linux || is_wasm || is_ohos) { - sources += [ "src/ports/SkDebug_stdio.cpp" ] - if (skia_use_egl) { - libs += [ "GLESv2" ] -@@ -1962,7 +2015,7 @@ if (skia_enable_tools) { ++ if (is_ohos) { ++ sources += [ "src/ports/SkDebug_ohos.cpp" ] ++ if (skia_use_egl) { ++ libs += [ "GLESv2" ] ++ } ++ libs += [ "hilog_ndk.z" ] ++ } ++ + if (is_mac) { + public += [ "include/ports/SkCFObject.h" ] + sources += [ +@@ -1962,7 +2023,7 @@ if (skia_enable_tools) { if (is_android || skia_use_egl) { sources += [ "tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp" ] libs += [ "EGL" ] @@ -160,7 +166,7 @@ index ebbd898ec9..2d4257e8d7 100644 sources += [ "tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp" ] libs += [ "GLU", -@@ -2281,7 +2334,7 @@ if (skia_enable_tools) { +@@ -2281,7 +2342,7 @@ if (skia_enable_tools) { ] } @@ -169,7 +175,7 @@ index ebbd898ec9..2d4257e8d7 100644 if (skia_enable_skottie) { test_app("skottie_tool") { deps = [ "modules/skottie:tool" ] -@@ -2777,7 +2830,7 @@ if (skia_enable_tools) { +@@ -2777,7 +2838,7 @@ if (skia_enable_tools) { "tools/sk_app/android/surface_glue_android.h", ] libs += [ "android" ] @@ -178,7 +184,7 @@ index ebbd898ec9..2d4257e8d7 100644 sources += [ "tools/SkGetExecutablePath_linux.cpp", "tools/sk_app/unix/RasterWindowContext_unix.cpp", -@@ -2830,7 +2883,7 @@ if (skia_enable_tools) { +@@ -2830,7 +2891,7 @@ if (skia_enable_tools) { sources += [ "tools/sk_app/GLWindowContext.h" ] if (is_android) { sources += [ "tools/sk_app/android/GLWindowContext_android.cpp" ] @@ -187,7 +193,7 @@ index ebbd898ec9..2d4257e8d7 100644 sources += [ "tools/sk_app/unix/GLWindowContext_unix.cpp" ] } else if (is_win) { sources += [ "tools/sk_app/win/GLWindowContext_win.cpp" ] -@@ -2855,7 +2908,7 @@ if (skia_enable_tools) { +@@ -2855,7 +2916,7 @@ if (skia_enable_tools) { sources += [ "tools/sk_app/VulkanWindowContext.h" ] if (is_android) { sources += [ "tools/sk_app/android/VulkanWindowContext_android.cpp" ] @@ -196,7 +202,7 @@ index ebbd898ec9..2d4257e8d7 100644 sources += [ "tools/sk_app/unix/VulkanWindowContext_unix.cpp" ] libs += [ "X11-xcb" ] } else if (is_win) { -@@ -2887,7 +2940,7 @@ if (skia_enable_tools) { +@@ -2887,7 +2948,7 @@ if (skia_enable_tools) { if (skia_use_dawn) { sources += [ "tools/sk_app/DawnWindowContext.cpp" ] sources += [ "tools/sk_app/DawnWindowContext.h" ] @@ -205,7 +211,7 @@ index ebbd898ec9..2d4257e8d7 100644 if (dawn_enable_vulkan) { sources += [ "tools/sk_app/unix/DawnVulkanWindowContext_unix.cpp" ] defines = [ "VK_USE_PLATFORM_XCB_KHR" ] -@@ -2931,7 +2984,7 @@ if (skia_enable_tools) { +@@ -2931,7 +2992,7 @@ if (skia_enable_tools) { } } @@ -214,7 +220,7 @@ index ebbd898ec9..2d4257e8d7 100644 test_app("fiddle_examples") { sources = [ "tools/fiddle/all_examples.cpp", -@@ -3088,7 +3141,7 @@ if (skia_enable_tools) { +@@ -3088,7 +3149,7 @@ if (skia_enable_tools) { } } @@ -327,6 +333,21 @@ index b43526fe1f..fb34289da7 100644 ldflags = [ "-rdynamic", "-Wl,-rpath,\$ORIGIN", +diff --git a/src/core/SkRRect.cpp b/src/core/SkRRect.cpp +index bdcf607d04..2e92ed05f3 100644 +--- a/src/core/SkRRect.cpp ++++ b/src/core/SkRRect.cpp +@@ -231,8 +231,8 @@ bool SkRRect::scaleRadii() { + double scale = 1.0; + + // The sides of the rectangle may be larger than a float. +- double width = (double)fRect.fRight - (double)fRect.fLeft; +- double height = (double)fRect.fBottom - (double)fRect.fTop; ++ double width = (double)(fRect.fRight - fRect.fLeft); ++ double height = (double)(fRect.fBottom - fRect.fTop); + scale = compute_min_scale(fRadii[0].fX, fRadii[1].fX, width, scale); + scale = compute_min_scale(fRadii[1].fY, fRadii[2].fY, height, scale); + scale = compute_min_scale(fRadii[2].fX, fRadii[3].fX, width, scale); diff --git a/src/gpu/ganesh/gl/egl/GrGLMakeEGLInterface.cpp b/src/gpu/ganesh/gl/egl/GrGLMakeEGLInterface.cpp index 78225b4610..c2105852b1 100644 --- a/src/gpu/ganesh/gl/egl/GrGLMakeEGLInterface.cpp @@ -1070,12 +1091,50 @@ index 0000000000..eb318dc3a3 +#endif + +#endif /* __gl2platform_h_ */ +diff --git a/src/ports/SkDebug_ohos.cpp b/src/ports/SkDebug_ohos.cpp +new file mode 100644 +index 0000000000..0e5e0829b6 +--- /dev/null ++++ b/src/ports/SkDebug_ohos.cpp +@@ -0,0 +1,32 @@ ++// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#include "include/core/SkTypes.h" ++ ++#include ++#include ++ ++ ++#ifdef HILOG_LOG_DOMAIN ++ #undef HILOG_LOG_DOMAIN ++#endif ++ ++#ifdef HILOG_LOG_TAG ++ #undef HILOG_LOG_DOMAIN ++#endif ++ ++ ++#define HILOG_LOG_DOMAIN 0x0000 ++#define HILOG_LOG_TAG "Skia" ++ ++void SkDebugf(const char format[], ...) { ++ char outStr[1024] = { 0 }; ++ va_list args; ++ va_start(args, format); ++ (void)vsnprintf(outStr,sizeof(outStr), format, args); ++ va_end(args); ++ ++ (void)OH_LOG_Print(LOG_APP, LOG_INFO, HILOG_LOG_DOMAIN,\ ++ HILOG_LOG_TAG, "%{public}s", outStr); ++} diff --git a/src/ports/skia_ohos/FontConfig_ohos.cpp b/src/ports/skia_ohos/FontConfig_ohos.cpp new file mode 100644 -index 0000000000..c502ed853e +index 0000000000..ea5c8ecf84 --- /dev/null +++ b/src/ports/skia_ohos/FontConfig_ohos.cpp -@@ -0,0 +1,1308 @@ +@@ -0,0 +1,1312 @@ +// Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. @@ -1138,6 +1197,10 @@ index 0000000000..c502ed853e + */ +int FontConfig_OHOS::getFamilyCount() const +{ ++#if ENABLE_DEBUG ++ dumpGeneric(); ++ dumpFallback(); ++#endif + return genericFamilySet.size(); +} + @@ -1490,7 +1553,7 @@ index 0000000000..c502ed853e + */ +void FontConfig_OHOS::dumpFont(const FontInfo& font) const +{ -+ LOGI("name=%s, family=%s, weight=%d, width=%d, slant=%d, index=%d", ++ SkDEBUGF("name=%s, family=%s, weight=%d, width=%d, slant=%d, index=%d", + font.fname.c_str(), font.familyName.c_str(), font.style.weight(), font.style.width(), font.style.slant(), + font.index); + int count = font.axisSet.axis.size(); @@ -1502,7 +1565,7 @@ index 0000000000..c502ed853e + str.append(","); + } + } -+ LOGI("axis={%s}\n", str.c_str()); ++ SkDEBUGF("axis={%s}\n", str.c_str()); + } +} + @@ -1510,9 +1573,9 @@ index 0000000000..c502ed853e + */ +void FontConfig_OHOS::dumpGeneric() const +{ -+ LOGI("\n"); ++ SkDEBUGF("\n"); + for (unsigned int i = 0; i < genericFamilySet.size(); i++) { -+ LOGI("[%d] familyName : %s - %d\n", i, genericFamilySet[i]->familyName.c_str(), ++ SkDEBUGF("[%d] familyName : %s - %d\n", i, genericFamilySet[i]->familyName.c_str(), + static_cast(genericFamilySet[i]->typefaceSet->size())); + for (int j = 0; j < genericFamilySet[i]->typefaceSet->size(); j++) { + if ((*(genericFamilySet[i]->typefaceSet))[j].get()) { @@ -1520,10 +1583,10 @@ index 0000000000..c502ed853e + if (font) { + dumpFont(*font); + } else { -+ LOGE("font [%d] is null\n", j); ++ SkDEBUGF("font [%d] is null\n", j); + } + } else { -+ LOGE("typefeace [%d] is null\n", j); ++ SkDEBUGF("typefeace [%d] is null\n", j); + } + } + } @@ -1533,21 +1596,21 @@ index 0000000000..c502ed853e + */ +void FontConfig_OHOS::dumpFallback() const +{ -+ LOGI("\n"); ++ SkDEBUGF("\n"); + int count = 0; + fallbackForMap.foreach([this, &count](const SkString& key, + const FallbackSetPos& setIndex) { -+ LOGI("[%d] family : %s - %d\n", count++, key.c_str(), setIndex.count); ++ SkDEBUGF("[%d] family : %s - %d\n", count++, key.c_str(), setIndex.count); + for (unsigned int i = setIndex.index; i < setIndex.index + setIndex.count; i++) { + const TypefaceSet& tpSet = *(fallbackSet[i]->typefaceSet.get()); -+ LOGI("[%s] - %d\n", fallbackSet[i]->familyName.c_str(), static_cast(tpSet.size())); ++ SkDEBUGF("[%s] - %d\n", fallbackSet[i]->familyName.c_str(), static_cast(tpSet.size())); + + for (unsigned int j = 0; j < tpSet.size(); j++) { + const FontInfo* font = tpSet[j]->getFontInfo(); + if (font) { + this->dumpFont(*font); + } else { -+ LOGE("font [%d] is null\n", j); ++ SkDEBUGF("font [%d] is null\n", j); + } + } + } @@ -1897,7 +1960,7 @@ index 0000000000..c502ed853e + if (root.size() != keyCount) { + text.appendf("%s#0", key); + errSet.emplace_back(ret, text.c_str()); -+ LOGE("%s : '%s' size should be 2, but here it's %d\n", errToString(ret), key, root.size()); ++ SkDEBUGF("%s : '%s' size should be 2, but here it's %d\n", errToString(ret), key, root.size()); + return ret; + } else if (!root[0].isString()) { + text.appendf("%s#1", key); @@ -2043,7 +2106,7 @@ index 0000000000..c502ed853e + } else { + err = ERROR_FONT_INVALID_STREAM; + } -+ LOGE("%s : %s\n", errToString(err), fname); ++ SkDEBUGF("%s : %s\n", errToString(err), fname); + char* fnameCopy = strdup(fname); + errSet.emplace_back(err, basename(fnameCopy)); + free(fnameCopy); @@ -2295,7 +2358,7 @@ index 0000000000..c502ed853e +{ + errSet.emplace_back(err, key); + if (err != ERROR_CONFIG_INVALID_VALUE_TYPE) { -+ LOGE("%s : %s\n", errToString(err), key); ++ SkDEBUGF("%s : %s\n", errToString(err), key); + } else { + const char* types[] = { + "null", @@ -2310,10 +2373,10 @@ index 0000000000..c502ed853e + int size = sizeof(types) / sizeof(char*); + if ((expected >= 0 && expected < size) && + (actual >= 0 && actual < size)) { -+ LOGE("%s : '%s' should be '%s', but here it's '%s'\n", ++ SkDEBUGF("%s : '%s' should be '%s', but here it's '%s'\n", + errToString(err), key, types[expected], types[actual]); + } else { -+ LOGE("%s : %s\n", errToString(err), key); ++ SkDEBUGF("%s : %s\n", errToString(err), key); + } + } + return err; @@ -2386,10 +2449,10 @@ index 0000000000..c502ed853e +} diff --git a/src/ports/skia_ohos/FontConfig_ohos.h b/src/ports/skia_ohos/FontConfig_ohos.h new file mode 100644 -index 0000000000..d23dc47c44 +index 0000000000..edd2c51495 --- /dev/null +++ b/src/ports/skia_ohos/FontConfig_ohos.h -@@ -0,0 +1,234 @@ +@@ -0,0 +1,217 @@ +// Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. @@ -2410,23 +2473,6 @@ index 0000000000..d23dc47c44 +#include "FontInfo_ohos.h" +#include "SkTypeface_ohos.h" + -+#ifdef ENABLE_DEBUG -+ -+#define LOGE(fmt, args...) \ -+ printf("E %s:%d %s - " fmt, basename(__FILE__), __LINE__, __FUNCTION__, ##args) -+#define LOGI(fmt, args...) \ -+ printf("I %s:%d - " fmt, __FUNCTION__, __LINE__, ##args) -+#define LOGW(fmt, args...) \ -+ printf("W %s:%d %s - " fmt, basename(__FILE__), __LINE__, __FUNCTION__, ##args) -+ -+#else -+ -+#define LOGE SkDEBUGF -+#define LOGI SkDEBUGF -+#define LOGW SkDEBUGF -+ -+#endif -+ +struct FontInfo; +struct FallbackInfo; +struct GenericFamily; @@ -2775,15 +2821,9 @@ index 0000000000..0b851ae3fa +}; + +#endif /* FONTINFO_OHOS_H */ -diff --git a/src/ports/skia_ohos/HmSymbolConfig_ohos.cpp b/src/ports/skia_ohos/HmSymbolConfig_ohos.cpp -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/src/ports/skia_ohos/HmSymbolConfig_ohos.h b/src/ports/skia_ohos/HmSymbolConfig_ohos.h -new file mode 100644 -index 0000000000..e69de29bb2 diff --git a/src/ports/skia_ohos/SkFontMgr_ohos.cpp b/src/ports/skia_ohos/SkFontMgr_ohos.cpp new file mode 100644 -index 0000000000..029d105ebc +index 0000000000..a18757d5d5 --- /dev/null +++ b/src/ports/skia_ohos/SkFontMgr_ohos.cpp @@ -0,0 +1,437 @@ @@ -2924,7 +2964,7 @@ index 0000000000..029d105ebc + } + } + if (item == nullptr) { -+ LOGE("%s : '%s' must be a fallback key in the config file\n", ++ SkDEBUGF("%s : '%s' must be a fallback key in the config file\n", + FontConfig_OHOS::errToString(ERROR_FAMILY_NOT_FOUND), defaultFamily.c_str()); + return nullptr; + } @@ -3142,7 +3182,7 @@ index 0000000000..029d105ebc + + std::unique_ptr stream = SkStreamAsset::MakeFromFile(path); + if (stream == nullptr) { -+ LOGE("%s : %s\n", FontConfig_OHOS::errToString(ERROR_FONT_NOT_EXIST), path); ++ SkDEBUGF("%s : %s\n", FontConfig_OHOS::errToString(ERROR_FONT_NOT_EXIST), path); + return nullptr; + } + SkFontArguments args; @@ -3169,7 +3209,7 @@ index 0000000000..029d105ebc + if (typeface) { + return sk_sp(typeface); + } -+ LOGE("%s\n", FontConfig_OHOS::errToString(ERROR_NO_AVAILABLE_FAMILY)); ++ SkDEBUGF("%s\n", FontConfig_OHOS::errToString(ERROR_NO_AVAILABLE_FAMILY)); + return nullptr; +} + @@ -3193,14 +3233,14 @@ index 0000000000..029d105ebc + if (axisCount == 0) { + if (!fontScanner.scanFont(stream.get(), ttcIndex, &fontInfo.familyName, &fontInfo.style, + &fontInfo.isFixedWidth, nullptr)) { -+ LOGE("%s\n", FontConfig_OHOS::errToString(ERROR_FONT_INVALID_STREAM)); ++ SkDEBUGF("%s\n", FontConfig_OHOS::errToString(ERROR_FONT_INVALID_STREAM)); + return nullptr; + } + } else { + AxisDefinitions axisDef; + if (!fontScanner.scanFont(stream.get(), ttcIndex, &fontInfo.familyName, &fontInfo.style, + &fontInfo.isFixedWidth, &axisDef)) { -+ LOGE("%s\n", FontConfig_OHOS::errToString(ERROR_FONT_INVALID_STREAM)); ++ SkDEBUGF("%s\n", FontConfig_OHOS::errToString(ERROR_FONT_INVALID_STREAM)); + return nullptr; + } + if (axisDef.size() > 0) { @@ -3467,10 +3507,10 @@ index 0000000000..b9fb40cf1e +#endif /* SKFONTSTYLESET_OHOS_H */ diff --git a/src/ports/skia_ohos/SkTypeface_ohos.cpp b/src/ports/skia_ohos/SkTypeface_ohos.cpp new file mode 100644 -index 0000000000..3141944c32 +index 0000000000..05d3d56d1b --- /dev/null +++ b/src/ports/skia_ohos/SkTypeface_ohos.cpp -@@ -0,0 +1,139 @@ +@@ -0,0 +1,165 @@ +// Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. @@ -3481,6 +3521,29 @@ index 0000000000..3141944c32 +#include "SkFontHost_FreeType_common.h" +#include "SkTArray.h" + ++#if ENABLE_DEBUG ++/*! To print out the font information ++ * \param font the font object to be printed ++ */ ++void DumpFont(const FontInfo& font) const ++{ ++ SkDEBUGF("name=%s, family=%s, weight=%d, width=%d, slant=%d, index=%d", ++ font.fname.c_str(), font.familyName.c_str(), font.style.weight(), font.style.width(), font.style.slant(), ++ font.index); ++ int count = font.axisSet.axis.size(); ++ if (count > 0) { ++ SkString str; ++ for (unsigned int i = 0; i < count; i++) { ++ str.appendU32(SkFixedFloorToInt(font.axisSet.axis[i])); ++ if (i < count - 1) { ++ str.append(","); ++ } ++ } ++ SkDEBUGF("axis={%s}\n", str.c_str()); ++ } ++} ++#endif ++ +/*! Constructor + * \param familyName the specified family name for the typeface + * \param info the font information for the typeface @@ -3537,6 +3600,9 @@ index 0000000000..3141944c32 + if (fontInfo->stream.get() == nullptr) { + return nullptr; + } ++#if ENABLE_DEBUG ++ DumpFont(*fontInfo); ++#endif + return std::make_unique(fontInfo->stream->duplicate(), fontInfo->index, 0, + fontInfo->axisSet.axis.data(), fontInfo->axisSet.axis.size(), nullptr, 0); +} -- Gitee From 9505ac3f917bf13d81178a68f7ffb96e7c069cf6 Mon Sep 17 00:00:00 2001 From: zjxi Date: Tue, 17 Dec 2024 15:04:34 +0800 Subject: [PATCH 12/15] =?UTF-8?q?refactor:=E5=B0=81=E8=A3=85=E5=AE=8F?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E5=88=A4=E6=96=AD=E7=A9=BA=E6=8C=87=E9=92=88?= =?UTF-8?q?=EF=BC=8C=E5=87=8F=E5=B0=91=E5=86=97=E4=BD=99=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E9=87=8F=EF=BC=8C=E5=A2=9E=E5=8A=A0=E4=BB=A3=E7=A0=81=E5=8F=AF?= =?UTF-8?q?=E8=AF=BB=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 1523 ++++++++--------- shell/platform/ohos/utils/ddl_utils.h | 1 + 2 files changed, 692 insertions(+), 832 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index 1224d30d56..ba0882e42c 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -30,14 +30,40 @@ #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 function %{public}s call, error code:%{public}d", \ - #X, RET); \ - } \ - } while (false) \ + +#define ARKUI_ACCESSIBILITY_CALL_CHECK(X) \ + do { \ + int32_t RET = X; \ + if (RET != ARKUI_SUCCEED_CODE) { \ + LOGE("Failed function %{public}s call, error code:%{public}d",\ + #X, RET); \ + } \ + } while (false) \ + +#define CHECK_DLL_NULL_PTR(func) \ + do { \ + if (func == nullptr) { \ + LOGE("Error: Function %{public}s is nullptr, %{public}s", \ + #func, LOAD_ERROR()); \ + } \ + } while (false) \ + +#define CHECK_NULL_PTR(PARAM, FUNC) \ + do { \ + if (PARAM == nullptr) { \ + LOGE("Error: %{public}s -> %{public}s is nullptr", \ + #FUNC, #PARAM); \ + } \ + } while (false) \ + +#define CHECK_NULL_PTR_WITH_RET(PARAM, FUNC) \ + do { \ + if (PARAM == nullptr) { \ + LOGE("Error: %{public}s -> %{public}s is nullptr", \ + #FUNC, #PARAM); \ + return ARKUI_FAILED_CODE; \ + } \ + } while (false) \ namespace flutter { @@ -151,12 +177,10 @@ void OhosAccessibilityBridge::UpdateSemantics( // 当滑动节点产生滑动,并执行滑动处理 if (HasScrolled(nodeEx)) { LOGD("UpdateSemantics -> has scrolled"); - ArkUI_AccessibilityElementInfo* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = + auto* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = OhosAccessibilityDDL::DLLoadCreateElemInfoFunc("OH_ArkUI_CreateAccessibilityElementInfo"); - if (OH_ArkUI_CreateAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_CreateAccessibilityElementInfo is null, %{public}s", dlerror()); - } - ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); + CHECK_DLL_NULL_PTR(OH_ArkUI_CreateAccessibilityElementInfo); + auto* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); FlutterNodeToElementInfoById(_elementInfo, static_cast(nodeEx.id)); // flutter滑动组件滑动处理逻辑 @@ -169,9 +193,7 @@ void OhosAccessibilityBridge::UpdateSemantics( void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); - if (OH_ArkUI_DestoryAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_DestoryAccessibilityElementInfo is null, %{public}s", dlerror()); - } + CHECK_DLL_NULL_PTR(OH_ArkUI_DestoryAccessibilityElementInfo); OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); _elementInfo = nullptr; } @@ -198,248 +220,204 @@ void OhosAccessibilityBridge::FlutterScrollExecution( SemanticsNodeExtent node, ArkUI_AccessibilityElementInfo* elementInfoFromList) { - if (OHOS_API_VERSION >= 13) { - 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 (OHOS_API_VERSION < 13) { return; } + double nodePosition = node.scrollPosition; + double nodeScrollExtentMax = node.scrollExtentMax; + double nodeScrollExtentMin = node.scrollExtentMin; + double infinity = std::numeric_limits::infinity(); - if (node.HasAction(ACTIONS_::kScrollUp) || - node.HasAction(ACTIONS_::kScrollDown)) { - } else if (node.HasAction(ACTIONS_::kScrollLeft) || - node.HasAction(ACTIONS_::kScrollRight)) { - LOGD("current flutterNode has scroll up/down/left/right"); + // 设置flutter可滑动的最大范围值 + if (nodeScrollExtentMax == infinity) { + nodeScrollExtentMax = SCROLL_EXTENT_FOR_INFINITY; + if (nodePosition > SCROLL_POSITION_CAP_FOR_INFINITY) { + nodePosition = SCROLL_POSITION_CAP_FOR_INFINITY; } - - // 当可滑动组件存在滑动子节点 - if (node.scrollChildren > 0) { - // 配置当前滑动组件的子节点总数 - int32_t itemCount = node.scrollChildren; - int32_t (*OH_ArkUI_AccessibilityElementInfoSetItemCount)(ArkUI_AccessibilityElementInfo*, int32_t) = - OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetItemCount"); - if (OH_ArkUI_AccessibilityElementInfoSetItemCount == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetItemCount is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetItemCount(elementInfoFromList, itemCount)); - - // 设置当前页面可见的起始滑动index - int32_t startItemIndex = node.scrollIndex; - int32_t (*OH_ArkUI_AccessibilityElementInfoSetStartItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = - OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetStartItemIndex"); - if (OH_ArkUI_AccessibilityElementInfoSetStartItemIndex == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetStartItemIndex is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, startItemIndex)); - - // 设置当前获焦节点的当前index - int32_t currItemIndex = accessibilityFocusedNode.id; - int32_t (*OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = - OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex"); - if (OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex(elementInfoFromList, currItemIndex)); - - // 计算当前滑动位置页面的可见子滑动节点数量 - int visibleChildren = 0; - // handle hidden children at the beginning and end of the list. - for (const auto& childId : node.childrenInHitTestOrder) { - auto childNode = GetFlutterSemanticsNode(childId); - if (!childNode.HasFlag(FLAGS_::kIsHidden)) { - visibleChildren += 1; - } - } - // 当可见滑动子节点数量超过滑动组件总子节点数量 - if (node.scrollIndex + visibleChildren > node.scrollChildren) { - FML_DLOG(WARNING) - << "FlutterScrollExecution -> Scroll index is out of bounds"; - } - // 当滑动击中子节点数量为0 - if (!node.childrenInHitTestOrder.size()) { - FML_DLOG(WARNING) << "FlutterScrollExecution -> Had scrollChildren but no " - "childrenInHitTestOrder"; - } - // 设置当前页面可见的末尾滑动index - int32_t endItemIndex = node.scrollIndex + visibleChildren - 1; - int32_t (*OH_ArkUI_AccessibilityElementInfoSetEndItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = - OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetEndItemIndex"); - if (OH_ArkUI_AccessibilityElementInfoSetEndItemIndex == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetEndItemIndex is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetEndItemIndex(elementInfoFromList, endItemIndex) - ); + } + 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; } -} -/** - * 特定节点的焦点请求 (当页面更新时自动请求id=0节点获焦) - */ -void OhosAccessibilityBridge::RequestFocusWhenPageUpdate(int32_t requestFocusId) -{ - if (provider_ == nullptr) { - FML_DLOG(ERROR) << "RequestFocusWhenPageUpdate ->" - "AccessibilityProvider = nullptr"; - return; + if (node.HasAction(ACTIONS_::kScrollUp) || + node.HasAction(ACTIONS_::kScrollDown)) { + } else if (node.HasAction(ACTIONS_::kScrollLeft) || + node.HasAction(ACTIONS_::kScrollRight)) { + LOGD("current flutterNode has scroll up/down/left/right"); } - if (OHOS_API_VERSION >= 13) { - ArkUI_AccessibilityEventInfo* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = - OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); - if (OH_ArkUI_CreateAccessibilityEventInfo == nullptr) { - LOGE("OH_ArkUI_CreateAccessibilityEventInfo is null, %{public}s", dlerror()); - } - ArkUI_AccessibilityEventInfo* reqFocusEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); - - ArkUI_AccessibilityElementInfo* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = - OhosAccessibilityDDL::DLLoadCreateElemInfoFunc("OH_ArkUI_CreateAccessibilityElementInfo"); - if (OH_ArkUI_CreateAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_CreateAccessibilityElementInfo is null, %{public}s", dlerror()); - } - ArkUI_AccessibilityElementInfo* elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); - int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = - OhosAccessibilityDDL::DLLoadSetEventFunc("OH_ArkUI_AccessibilityEventSetEventType"); - if (OH_ArkUI_AccessibilityEventSetEventType == nullptr) { - LOGE("OH_ArkUI_AccessibilityEventSetEventType is null, %{public}s", dlerror()); - } + // 当可滑动组件存在滑动子节点 + if (node.scrollChildren > 0) { + // 配置当前滑动组件的子节点总数 + int32_t itemCount = node.scrollChildren; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetItemCount)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetItemCount"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetItemCount); ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityEventSetEventType( - reqFocusEventInfo, - ArkUI_AccessibilityEventType:: - ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_REQUEST_ACCESSIBILITY_FOCUS) - ); + OH_ArkUI_AccessibilityElementInfoSetItemCount(elementInfoFromList, itemCount)); - int32_t (*OH_ArkUI_AccessibilityEventSetRequestFocusId)(ArkUI_AccessibilityEventInfo*, int32_t) = - OhosAccessibilityDDL::DLLoadSetReqFocusFunc("OH_ArkUI_AccessibilityEventSetRequestFocusId"); - if (OH_ArkUI_AccessibilityEventSetRequestFocusId == nullptr) { - LOGE("OH_ArkUI_AccessibilityEventSetRequestFocusId is null, %{public}s", dlerror()); - } + // 设置当前页面可见的起始滑动index + int32_t startItemIndex = node.scrollIndex; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetStartItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetStartItemIndex"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetStartItemIndex); ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityEventSetRequestFocusId(reqFocusEventInfo, - requestFocusId) - ); + OH_ArkUI_AccessibilityElementInfoSetStartItemIndex(elementInfoFromList, startItemIndex)); - int32_t (*OH_ArkUI_AccessibilityEventSetElementInfo)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityElementInfo*) = - OhosAccessibilityDDL::DLLoadSetEventElemFunc("OH_ArkUI_AccessibilityEventSetElementInfo"); - if (OH_ArkUI_AccessibilityEventSetElementInfo == nullptr) { - LOGE("OH_ArkUI_AccessibilityEventSetElementInfo is null, %{public}s", dlerror()); + // 设置当前获焦节点的当前index + int32_t currItemIndex = accessibilityFocusedNode.id; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetCurrentItemIndex(elementInfoFromList, currItemIndex)); + + // 计算当前滑动位置页面的可见子滑动节点数量 + int visibleChildren = 0; + // handle hidden children at the beginning and end of the list. + for (const auto& childId : node.childrenInHitTestOrder) { + auto childNode = GetFlutterSemanticsNode(childId); + if (!childNode.HasFlag(FLAGS_::kIsHidden)) { + visibleChildren += 1; + } } + // 当可见滑动子节点数量超过滑动组件总子节点数量 + if (node.scrollIndex + visibleChildren > node.scrollChildren) { + FML_DLOG(WARNING) + << "FlutterScrollExecution -> Scroll index is out of bounds"; + } + // 当滑动击中子节点数量为0 + if (!node.childrenInHitTestOrder.size()) { + FML_DLOG(WARNING) << "FlutterScrollExecution -> Had scrollChildren but no " + "childrenInHitTestOrder"; + } + // 设置当前页面可见的末尾滑动index + int32_t endItemIndex = node.scrollIndex + visibleChildren - 1; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEndItemIndex)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetEndItemIndex"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetEndItemIndex); ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityEventSetElementInfo(reqFocusEventInfo, elementInfo) + OH_ArkUI_AccessibilityElementInfoSetEndItemIndex(elementInfoFromList, endItemIndex) ); - - auto callback = [](int32_t errorCode) { - FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; - }; - - void (*OH_ArkUI_SendAccessibilityAsyncEvent)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*callback)(int32_t)) = - OhosAccessibilityDDL::DLLoadSendAsyncEventFunc("OH_ArkUI_SendAccessibilityAsyncEvent"); - if (OH_ArkUI_SendAccessibilityAsyncEvent == nullptr) { - LOGE("OH_ArkUI_SendAccessibilityAsyncEvent is null, %{public}s", dlerror()); - } - OH_ArkUI_SendAccessibilityAsyncEvent(provider_, reqFocusEventInfo, callback); - - void (*OH_ArkUI_DestoryAccessibilityEventInfo)(ArkUI_AccessibilityEventInfo*) = - OhosAccessibilityDDL::DLLoadDestroyEventFunc("OH_ArkUI_DestoryAccessibilityEventInfo"); - if (OH_ArkUI_DestoryAccessibilityEventInfo == nullptr) { - LOGE("OH_ArkUI_DestoryAccessibilityEventInfo is null, %{public}s", dlerror()); - } - OH_ArkUI_DestoryAccessibilityEventInfo(reqFocusEventInfo); - reqFocusEventInfo = nullptr; - - void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = - OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); - if (OH_ArkUI_DestoryAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_DestoryAccessibilityElementInfo is null, %{public}s", dlerror()); - } - OH_ArkUI_DestoryAccessibilityElementInfo(elementInfo); - elementInfo = nullptr; } } +/** + * 特定节点的焦点请求 (当页面更新时自动请求id=0节点获焦) + */ +void OhosAccessibilityBridge::RequestFocusWhenPageUpdate(int32_t requestFocusId) +{ + if (OHOS_API_VERSION < 13) { return; } + CHECK_NULL_PTR(provider_, RequestFocusWhenPageUpdate); + + auto* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = + OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); + CHECK_DLL_NULL_PTR(OH_ArkUI_CreateAccessibilityEventInfo); + auto* reqFocusEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); + + auto* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = + OhosAccessibilityDDL::DLLoadCreateElemInfoFunc("OH_ArkUI_CreateAccessibilityElementInfo"); + CHECK_DLL_NULL_PTR(OH_ArkUI_CreateAccessibilityElementInfo); + auto* elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); + + int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = + OhosAccessibilityDDL::DLLoadSetEventFunc("OH_ArkUI_AccessibilityEventSetEventType"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityEventSetEventType); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetEventType( + reqFocusEventInfo, + ArkUI_AccessibilityEventType:: + ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_REQUEST_ACCESSIBILITY_FOCUS) + ); + + int32_t (*OH_ArkUI_AccessibilityEventSetRequestFocusId)(ArkUI_AccessibilityEventInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetReqFocusFunc("OH_ArkUI_AccessibilityEventSetRequestFocusId"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityEventSetRequestFocusId); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetRequestFocusId(reqFocusEventInfo, requestFocusId) + ); + + int32_t (*OH_ArkUI_AccessibilityEventSetElementInfo)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityElementInfo*) = + OhosAccessibilityDDL::DLLoadSetEventElemFunc("OH_ArkUI_AccessibilityEventSetElementInfo"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityEventSetElementInfo); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetElementInfo(reqFocusEventInfo, elementInfo) + ); + + auto callback = [](int32_t errorCode) { + FML_DLOG(WARNING) << "PageStateUpdate callback-> errorCode =" << errorCode; + }; + + void (*OH_ArkUI_SendAccessibilityAsyncEvent)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*callback)(int32_t)) = + OhosAccessibilityDDL::DLLoadSendAsyncEventFunc("OH_ArkUI_SendAccessibilityAsyncEvent"); + CHECK_DLL_NULL_PTR(OH_ArkUI_SendAccessibilityAsyncEvent); + OH_ArkUI_SendAccessibilityAsyncEvent(provider_, reqFocusEventInfo, callback); + + void (*OH_ArkUI_DestoryAccessibilityEventInfo)(ArkUI_AccessibilityEventInfo*) = + OhosAccessibilityDDL::DLLoadDestroyEventFunc("OH_ArkUI_DestoryAccessibilityEventInfo"); + CHECK_DLL_NULL_PTR(OH_ArkUI_DestoryAccessibilityEventInfo); + OH_ArkUI_DestoryAccessibilityEventInfo(reqFocusEventInfo); + reqFocusEventInfo = nullptr; + + void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = + OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); + CHECK_DLL_NULL_PTR(OH_ArkUI_DestoryAccessibilityElementInfo); + OH_ArkUI_DestoryAccessibilityElementInfo(elementInfo); + elementInfo = nullptr; +} + /** * 主动播报特定文本 */ void OhosAccessibilityBridge::Announce(std::unique_ptr& message) { - if (provider_ == nullptr) { - FML_DLOG(ERROR) << "announce ->" - "AccessibilityProvider = nullptr"; - return; - } - if (OHOS_API_VERSION >= 13) { - // 创建并设置屏幕朗读事件 - ArkUI_AccessibilityEventInfo* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = - OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); - if (OH_ArkUI_CreateAccessibilityEventInfo == nullptr) { - LOGE("OH_ArkUI_CreateAccessibilityEventInfo is null, %{public}s", dlerror()); - } - ArkUI_AccessibilityEventInfo* announceEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); - - - int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = - OhosAccessibilityDDL::DLLoadSetEventFunc("OH_ArkUI_AccessibilityEventSetEventType"); - if (OH_ArkUI_AccessibilityEventSetEventType == nullptr) { - LOGE("OH_ArkUI_AccessibilityEventSetEventType is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityEventSetEventType( - announceEventInfo, - ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ANNOUNCE_FOR_ACCESSIBILITY) - ); - - int32_t (*OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility)(ArkUI_AccessibilityEventInfo*, const char*) = - OhosAccessibilityDDL::DLLoadSetEventStringFunc("OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility"); - if (OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility == nullptr) { - LOGE("OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility( - announceEventInfo, message.get()) - ); - FML_DLOG(INFO) << ("announce -> message: ") << (message.get()); - - auto callback = [](int32_t errorCode) { - FML_DLOG(WARNING) << "announce callback-> errorCode =" << errorCode; - }; - - void (*OH_ArkUI_SendAccessibilityAsyncEvent)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*callback)(int32_t)) = - OhosAccessibilityDDL::DLLoadSendAsyncEventFunc("OH_ArkUI_SendAccessibilityAsyncEvent"); - if (OH_ArkUI_SendAccessibilityAsyncEvent == nullptr) { - LOGE("OH_ArkUI_SendAccessibilityAsyncEvent is null, %{public}s", dlerror()); - } - OH_ArkUI_SendAccessibilityAsyncEvent(provider_, announceEventInfo, callback); - - void (*OH_ArkUI_DestoryAccessibilityEventInfo)(ArkUI_AccessibilityEventInfo*) = - OhosAccessibilityDDL::DLLoadDestroyEventFunc("OH_ArkUI_DestoryAccessibilityEventInfo"); - if (OH_ArkUI_DestoryAccessibilityEventInfo == nullptr) { - LOGE("OH_ArkUI_DestoryAccessibilityEventInfo is null, %{public}s", dlerror()); - } - OH_ArkUI_DestoryAccessibilityEventInfo(announceEventInfo); - announceEventInfo = nullptr; - } + if (OHOS_API_VERSION < 13) { return; } + CHECK_NULL_PTR(provider_, Announce); + + // 创建并设置屏幕朗读事件 + auto* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = + OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); + CHECK_DLL_NULL_PTR(OH_ArkUI_CreateAccessibilityEventInfo); + auto* announceEventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); + + + int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = + OhosAccessibilityDDL::DLLoadSetEventFunc("OH_ArkUI_AccessibilityEventSetEventType"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityEventSetEventType); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetEventType( + announceEventInfo, + ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ANNOUNCE_FOR_ACCESSIBILITY) + ); + + int32_t (*OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility)(ArkUI_AccessibilityEventInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetEventStringFunc("OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityEventSetTextAnnouncedForAccessibility( + announceEventInfo, message.get()) + ); + FML_DLOG(INFO) << ("announce -> message: ") << (message.get()); + + auto callback = [](int32_t errorCode) { + FML_DLOG(WARNING) << "announce callback-> errorCode =" << errorCode; + }; + + void (*OH_ArkUI_SendAccessibilityAsyncEvent)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*callback)(int32_t)) = + OhosAccessibilityDDL::DLLoadSendAsyncEventFunc("OH_ArkUI_SendAccessibilityAsyncEvent"); + CHECK_DLL_NULL_PTR(OH_ArkUI_SendAccessibilityAsyncEvent); + OH_ArkUI_SendAccessibilityAsyncEvent(provider_, announceEventInfo, callback); + + void (*OH_ArkUI_DestoryAccessibilityEventInfo)(ArkUI_AccessibilityEventInfo*) = + OhosAccessibilityDDL::DLLoadDestroyEventFunc("OH_ArkUI_DestoryAccessibilityEventInfo"); + CHECK_DLL_NULL_PTR(OH_ArkUI_DestoryAccessibilityEventInfo); + OH_ArkUI_DestoryAccessibilityEventInfo(announceEventInfo); + announceEventInfo = nullptr; } //获取根节点 @@ -617,11 +595,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId) { - if (elementInfoFromList == nullptr) { - FML_DLOG(INFO) << "OhosAccessibilityBridge::FlutterNodeToElementInfoById " - "elementInfoFromList is null"; - return; - } + CHECK_NULL_PTR(elementInfoFromList, FlutterNodeToElementInfoById); FML_DLOG(INFO) << "FlutterNodeToElementInfoById elementId = " << elementId; // 当elementId = -1或0时,创建root节点 @@ -640,9 +614,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( ArkUI_AccessibleRect rect = {left, top, right, bottom}; int32_t (*OH_ArkUI_AccessibilityElementInfoSetScreenRect)(ArkUI_AccessibilityElementInfo*, ArkUI_AccessibleRect*) = OhosAccessibilityDDL::DLLoadSetElemSreenRectFunc("OH_ArkUI_AccessibilityElementInfoSetScreenRect"); - if (OH_ArkUI_AccessibilityElementInfoSetScreenRect == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetScreenRect is null, %{public}s", dlerror()); - } + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetScreenRect); ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect) ); @@ -656,17 +628,13 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( // 根据flutternode信息配置对应的elementinfo int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetElementId"); - if (OH_ArkUI_AccessibilityElementInfoSetElementId == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetElementId is null, %{public}s", dlerror()); - } + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetElementId); ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, 0)); // NOTE: arkui无障碍子系统强制设置root的父节点id = -2100000 (严禁更改) int32_t (*OH_ArkUI_AccessibilityElementInfoSetParentId)(ArkUI_AccessibilityElementInfo*, int32_t) = OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetParentId"); - if (OH_ArkUI_AccessibilityElementInfoSetParentId == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetParentId is null, %{public}s", dlerror()); - } + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetParentId); ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, ARKUI_ACCESSIBILITY_ROOT_PARENT_ID) ); @@ -674,9 +642,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( // 设置无障碍播报文本 int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityText)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText"); - if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityText == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText is null, %{public}s", dlerror()); - } + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetAccessibilityText); ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityElementInfoSetAccessibilityText( elementInfoFromList, flutterNode.label.empty() ? @@ -685,18 +651,14 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel"); - if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel is null, %{public}s", dlerror()); - } + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel); ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes") ); int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup"); - if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup is null, %{public}s", dlerror()); - } + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup); ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, false) ); @@ -715,9 +677,7 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( } int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); - if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); - } + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetChildNodeIds); ARKUI_ACCESSIBILITY_CALL_CHECK( OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds) ); @@ -726,44 +686,32 @@ void OhosAccessibilityBridge::FlutterNodeToElementInfoById( // 配置root节点常用属性 int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); - if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); - } + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetEnabled); ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true)); int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); - if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); - } + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetClickable); ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true)); int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetFocusable"); - if (OH_ArkUI_AccessibilityElementInfoSetFocusable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetFocusable is null, %{public}s", dlerror()); - } + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetFocusable); ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true)); int32_t (*OH_ArkUI_AccessibilityElementInfoSetVisible)(ArkUI_AccessibilityElementInfo*, bool) = OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetVisible"); - if (OH_ArkUI_AccessibilityElementInfoSetVisible == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetVisible is null, %{public}s", dlerror()); - } + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetVisible); ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true)); int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetComponentType"); - if (OH_ArkUI_AccessibilityElementInfoSetComponentType == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetComponentType is null, %{public}s", dlerror()); - } + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetComponentType); ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root")); int32_t (*OH_ArkUI_AccessibilityElementInfoSetContents)(ArkUI_AccessibilityElementInfo*, const char*) = OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetContents"); - if (OH_ArkUI_AccessibilityElementInfoSetContents == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetContents is null, %{public}s", dlerror()); - } + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetContents); ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, flutterNode.label.c_str())); } else { //当elementId >= 1时,根据flutter节点信息配置elementinfo无障碍属性 @@ -780,110 +728,107 @@ void OhosAccessibilityBridge::FlutterSetElementInfoOperationActions( ArkUI_AccessibilityElementInfo* elementInfoFromList, std::string widget_type) { - if (OHOS_API_VERSION >= 13) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetOperationActions)(ArkUI_AccessibilityElementInfo*, int32_t, ArkUI_AccessibleAction*) = - OhosAccessibilityDDL::DLLoadSetElemOperActionsFunc("OH_ArkUI_AccessibilityElementInfoSetOperationActions"); - if (OH_ArkUI_AccessibilityElementInfoSetOperationActions == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetOperationActions is null, %{public}s", dlerror()); - } - if (OHOSUtils::Contains(widget_type, EDIT_TEXT_WIDGET_NAME) || - OHOSUtils::Contains(widget_type, EDIT_MULTILINE_TEXT_WIDGET_NAME)) { - // set elementinfo action types - int32_t actionTypeNum = 10; - ArkUI_AccessibleAction actions[actionTypeNum]; + if (OHOS_API_VERSION < 13) { return; } + int32_t (*OH_ArkUI_AccessibilityElementInfoSetOperationActions)(ArkUI_AccessibilityElementInfo*, int32_t, ArkUI_AccessibleAction*) = + OhosAccessibilityDDL::DLLoadSetElemOperActionsFunc("OH_ArkUI_AccessibilityElementInfoSetOperationActions"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetOperationActions); + if (OHOSUtils::Contains(widget_type, EDIT_TEXT_WIDGET_NAME) || + OHOSUtils::Contains(widget_type, EDIT_MULTILINE_TEXT_WIDGET_NAME)) { + // 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[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[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[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[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[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[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[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[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[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 = "光标位置设置"; + actions[9].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION; + actions[9].description = "光标位置设置"; - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions) - ); - } else if (OHOSUtils::Contains(widget_type, SCROLL_WIDGET_NAME)) { - // if node is a scrollable component - int32_t actionTypeNum = 5; - ArkUI_AccessibleAction actions[actionTypeNum]; + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions) + ); + } else if (OHOSUtils::Contains(widget_type, SCROLL_WIDGET_NAME)) { + // 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[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[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[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[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[4].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD; + actions[4].description = "向下滑动"; - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions) - ); - } else { - // set common component action types - int32_t actionTypeNum = 3; - ArkUI_AccessibleAction actions[actionTypeNum]; + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions) + ); + } else { + // set common component action types + int32_t actionTypeNum = 3; + ArkUI_AccessibleAction actions[actionTypeNum]; - actions[0].actionType = ArkUI_Accessibility_ActionType:: - ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS; - actions[0].description = "获取焦点"; + actions[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[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[2].actionType = ArkUI_Accessibility_ActionType:: + ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK; + actions[2].description = "点击动作"; - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions) - ); - } + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetOperationActions(elementInfoFromList, actionTypeNum, actions) + ); } } @@ -894,318 +839,275 @@ void OhosAccessibilityBridge::FlutterSetElementInfoProperties( ArkUI_AccessibilityElementInfo* elementInfoFromList, int64_t elementId) { - if (OHOS_API_VERSION >= 13) { - SemanticsNodeExtent flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); - if (flutterNode.isNull) { - LOGE("FlutterSetElementInfoProperties: GetFlutterSemanticsNode id=%{public}ld null", elementId); - } + if (OHOS_API_VERSION < 13) { return; } + auto flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); + if (!g_flutterSemanticsTree.count(flutterNode.id)) { + LOGE("FlutterSetElementInfoProperties: GetFlutterSemanticsNode id=%{public}ld null", elementId); + } + + // set elementinfo id + int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetElementId"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetElementId); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, flutterNode.id) + ); + + // 相对-绝对坐标映射 + FlutterRelativeRectToScreenRect(flutterNode); + auto [left, top, right, bottom] = GetAbsoluteScreenRect(flutterNode); + ArkUI_AccessibleRect rect = {static_cast(left), static_cast(top), + static_cast(right), static_cast(bottom)}; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetScreenRect)(ArkUI_AccessibilityElementInfo*, ArkUI_AccessibleRect*) = + OhosAccessibilityDDL::DLLoadSetElemSreenRectFunc("OH_ArkUI_AccessibilityElementInfoSetScreenRect"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetScreenRect); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect) + ); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> node.id= " + << flutterNode.id << " SceenRect = (" << left << ", " << top + << ", " << right << ", " << bottom << ")"; + + // 配置arkui的elementinfo可操作动作属性 + if (IsTextField(flutterNode)) { + // 若当前flutter节点为文本输入框组件 + std::string widgeType = flutterNode.HasFlag(FLAGS_::kIsMultiline) ? + EDIT_MULTILINE_TEXT_WIDGET_NAME : EDIT_TEXT_WIDGET_NAME; + FlutterSetElementInfoOperationActions(elementInfoFromList, widgeType); + } else if (IsScrollableWidget(flutterNode) || IsNodeScrollable(flutterNode)) { + // 若当前flutter节点为可滑动组件类型 + FlutterSetElementInfoOperationActions(elementInfoFromList, SCROLL_WIDGET_NAME); + } else { + // 若当前flutter节点为通用组件 + FlutterSetElementInfoOperationActions(elementInfoFromList, OTHER_WIDGET_NAME); + } - // set elementinfo id - int32_t (*OH_ArkUI_AccessibilityElementInfoSetElementId)(ArkUI_AccessibilityElementInfo*, int32_t) = - OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetElementId"); - if (OH_ArkUI_AccessibilityElementInfoSetElementId == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetElementId is null, %{public}s", dlerror()); - } + // 设置当前节点的父节点id + int32_t parentId = GetParentId(elementId); + int32_t (*OH_ArkUI_AccessibilityElementInfoSetParentId)(ArkUI_AccessibilityElementInfo*, int32_t) = + OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetParentId"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetParentId); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, parentId) + ); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById GetParentId = " << parentId; + + // 设置可朗读文本 + std::string text = flutterNode.label + flutterNode.value; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityText)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetAccessibilityText); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfoFromList, text.c_str()) + ); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetAccessibilityText = " << text; + + // 设置无障碍content文本 + int32_t (*OH_ArkUI_AccessibilityElementInfoSetContents)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetContents"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetContents); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, text.c_str()) + ); + // 设置hint提示文本 + std::string hint = flutterNode.hint; + int32_t (*OH_ArkUI_AccessibilityElementInfoSetHintText)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetHintText"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetHintText); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetHintText(elementInfoFromList, hint.c_str()) + ); + + // 设置当前节点的全部孩子节点 + int32_t childCount = flutterNode.childrenInTraversalOrder.size(); + if (childCount > 0) { + auto childrenIdsVec = flutterNode.childrenInTraversalOrder; + std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); + int64_t childNodeIds[childCount]; + for (int32_t i = 0; i < childCount; i++) { + childNodeIds[i] = static_cast(childrenIdsVec[i]); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> elementid=" << elementId + << " childCount=" << childCount + << " childNodeIds=" << childNodeIds[i]; + } + int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = + OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetChildNodeIds); ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetElementId(elementInfoFromList, flutterNode.id) + OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds) ); + } - // 相对-绝对坐标映射 - FlutterRelativeRectToScreenRect(flutterNode); - auto [left, top, right, bottom] = GetAbsoluteScreenRect(flutterNode); - ArkUI_AccessibleRect rect = {static_cast(left), static_cast(top), - static_cast(right), static_cast(bottom)}; - int32_t (*OH_ArkUI_AccessibilityElementInfoSetScreenRect)(ArkUI_AccessibilityElementInfo*, ArkUI_AccessibleRect*) = - OhosAccessibilityDDL::DLLoadSetElemSreenRectFunc("OH_ArkUI_AccessibilityElementInfoSetScreenRect"); - if (OH_ArkUI_AccessibilityElementInfoSetScreenRect == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetScreenRect is null, %{public}s", dlerror()); - } + /** + * 根据当前flutter节点的SemanticsFlags特性,配置对应的elmentinfo属性 + */ + // 判断当前节点组件是否enabled + if (IsNodeEnabled(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetEnabled); ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetScreenRect(elementInfoFromList, &rect) + OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true) ); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> node.id= " - << flutterNode.id << " SceenRect = (" << left << ", " << top - << ", " << right << ", " << bottom << ")"; - - // 配置arkui的elementinfo可操作动作属性 - if (IsTextField(flutterNode)) { - // 若当前flutter节点为文本输入框组件 - std::string widgeType = flutterNode.HasFlag(FLAGS_::kIsMultiline) ? - EDIT_MULTILINE_TEXT_WIDGET_NAME : EDIT_TEXT_WIDGET_NAME; - FlutterSetElementInfoOperationActions(elementInfoFromList, widgeType); - } else if (IsScrollableWidget(flutterNode) || IsNodeScrollable(flutterNode)) { - // 若当前flutter节点为可滑动组件类型 - FlutterSetElementInfoOperationActions(elementInfoFromList, SCROLL_WIDGET_NAME); - } else { - // 若当前flutter节点为通用组件 - FlutterSetElementInfoOperationActions(elementInfoFromList, OTHER_WIDGET_NAME); - } - - // 设置当前节点的父节点id - int32_t parentId = GetParentId(elementId); - int32_t (*OH_ArkUI_AccessibilityElementInfoSetParentId)(ArkUI_AccessibilityElementInfo*, int32_t) = - OhosAccessibilityDDL::DLLoadSetElemIntFunc("OH_ArkUI_AccessibilityElementInfoSetParentId"); - if (OH_ArkUI_AccessibilityElementInfoSetParentId == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetParentId is null, %{public}s", dlerror()); - } + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetEnabled -> true"; + } + // 判断当前节点是否可点击 + if (IsNodeClickable(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetClickable); ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetParentId(elementInfoFromList, parentId) + OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true) ); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById GetParentId = " << parentId; - - // 设置可朗读文本 - std::string text = flutterNode.label + flutterNode.value; - int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityText)(ArkUI_AccessibilityElementInfo*, const char*) = - OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText"); - if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityText == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityText is null, %{public}s", dlerror()); - } + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetClickable -> true"; + } + // 判断当前节点是否可获焦点 + if (IsNodeFocusable(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetFocusable"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetFocusable); ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityText(elementInfoFromList, text.c_str()) + OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true) ); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetAccessibilityText = " << text; - - // 设置无障碍content文本 - int32_t (*OH_ArkUI_AccessibilityElementInfoSetContents)(ArkUI_AccessibilityElementInfo*, const char*) = - OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetContents"); - if (OH_ArkUI_AccessibilityElementInfoSetContents == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetContents is null, %{public}s", dlerror()); - } + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetFocusable -> true"; + } + // 判断当前节点是否为密码输入框 + if (IsNodePassword(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetIsPassword)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetIsPassword"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetIsPassword); ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetContents(elementInfoFromList, text.c_str()) + OH_ArkUI_AccessibilityElementInfoSetIsPassword(elementInfoFromList, true) ); - // 设置hint提示文本 - std::string hint = flutterNode.hint; - int32_t (*OH_ArkUI_AccessibilityElementInfoSetHintText)(ArkUI_AccessibilityElementInfo*, const char*) = - OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetHintText"); - if (OH_ArkUI_AccessibilityElementInfoSetHintText == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetHintText is null, %{public}s", dlerror()); - } + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetIsPassword -> true"; + } + // 判断当前节点是否具备checkable状态 (如:checkbox, radio button) + if (IsNodeCheckable(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetCheckable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetCheckable"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetCheckable); ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetHintText(elementInfoFromList, hint.c_str()) + OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true) ); - - // 设置当前节点的全部孩子节点 - int32_t childCount = flutterNode.childrenInTraversalOrder.size(); - if (childCount > 0) { - auto childrenIdsVec = flutterNode.childrenInTraversalOrder; - std::sort(childrenIdsVec.begin(), childrenIdsVec.end()); - int64_t childNodeIds[childCount]; - for (int32_t i = 0; i < childCount; i++) { - childNodeIds[i] = static_cast(childrenIdsVec[i]); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById -> elementid=" << elementId - << " childCount=" << childCount - << " childNodeIds=" << childNodeIds[i]; - } - int32_t (*OH_ArkUI_AccessibilityElementInfoSetChildNodeIds)(ArkUI_AccessibilityElementInfo*, int32_t, int64_t*) = - OhosAccessibilityDDL::DLLoadSetElemChildFunc("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds"); - if (OH_ArkUI_AccessibilityElementInfoSetChildNodeIds == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetChildNodeIds is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetChildNodeIds(elementInfoFromList, childCount, childNodeIds) - ); - } - - /** - * 根据当前flutter节点的SemanticsFlags特性,配置对应的elmentinfo属性 - */ - // 判断当前节点组件是否enabled - if (IsNodeEnabled(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetEnabled)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEnabled"); - if (OH_ArkUI_AccessibilityElementInfoSetEnabled == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetEnabled is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetEnabled(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetEnabled -> true"; - } - // 判断当前节点是否可点击 - if (IsNodeClickable(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetClickable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetClickable"); - if (OH_ArkUI_AccessibilityElementInfoSetClickable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetClickable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetClickable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetClickable -> true"; - } - // 判断当前节点是否可获焦点 - if (IsNodeFocusable(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetFocusable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetFocusable"); - if (OH_ArkUI_AccessibilityElementInfoSetFocusable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetFocusable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetFocusable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetFocusable -> true"; - } - // 判断当前节点是否为密码输入框 - if (IsNodePassword(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetIsPassword)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetIsPassword"); - if (OH_ArkUI_AccessibilityElementInfoSetIsPassword == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetIsPassword is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetIsPassword(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetIsPassword -> true"; - } - // 判断当前节点是否具备checkable状态 (如:checkbox, radio button) - if (IsNodeCheckable(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetCheckable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetCheckable"); - if (OH_ArkUI_AccessibilityElementInfoSetCheckable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetCheckable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetCheckable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetCheckable -> true"; - } - // 判断当前节点(check box/radio button)是否checked/unchecked - if (IsNodeChecked(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetChecked)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetChecked"); - if (OH_ArkUI_AccessibilityElementInfoSetChecked == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetChecked is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetChecked(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetChecked -> true"; - } - // 判断当前节点组件是否可显示 - if (IsNodeVisible(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetVisible)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetVisible"); - if (OH_ArkUI_AccessibilityElementInfoSetVisible == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetVisible is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetVisible -> true"; - } - // 判断当前节点组件是否选中 - if (IsNodeSelected(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetSelected)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetSelected"); - if (OH_ArkUI_AccessibilityElementInfoSetSelected == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetSelected is null, %{public}s", dlerror()); - } - OH_ArkUI_AccessibilityElementInfoSetSelected(elementInfoFromList, true); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetSelected -> true"; - } - // 判断当前节点组件是否可滑动 - if (IsNodeScrollable(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetScrollable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetScrollable"); - if (OH_ArkUI_AccessibilityElementInfoSetScrollable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetScrollable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetScrollable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetScrollable -> true"; - } - // 判断当前节点组件是否可编辑(文本输入框) - if (IsTextField(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetEditable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEditable"); - if (OH_ArkUI_AccessibilityElementInfoSetEditable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetEditable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetEditable(elementInfoFromList, true) - ); - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetEditable -> true"; - } - // 判断当前节点组件是否为滑动条 - if (IsSlider(flutterNode)) { - FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetRangeInfo -> true"; - } - // 判断当前节点组件是否支持长按 - if (IsNodeHasLongPress(flutterNode)) { - int32_t (*OH_ArkUI_AccessibilityElementInfoSetLongClickable)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetLongClickable"); - if (OH_ArkUI_AccessibilityElementInfoSetLongClickable == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetLongClickable is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetLongClickable(elementInfoFromList, true) - ); - FML_DLOG(INFO) - << "flutterNode.id=" << flutterNode.id - << " OH_ArkUI_AccessibilityElementInfoSetLongClickable -> true"; - } - - // 获取当前节点的组件类型 - std::string componentTypeName = GetNodeComponentType(flutterNode); - FML_DLOG(INFO) << "FlutterNodeToElementInfoById componentTypeName = " - << componentTypeName; - // flutter节点对应elementinfo所属的组件类型(如:root, button,text等) - int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = - OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetComponentType"); - if (OH_ArkUI_AccessibilityElementInfoSetComponentType == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetComponentType is null, %{public}s", dlerror()); - } - if (elementId == 0) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root") - ); - } else { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, - componentTypeName.c_str()) - ); - } - FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetComponentType: " - << componentTypeName; - - /** - * 无障碍重要性,用于控制某个组件是否可被无障碍辅助服务所识别。支持的值为(默认值:“auto”): - * “auto”:根据组件不同会转换为“yes”或者“no” - * “yes”:当前组件可被无障碍辅助服务所识别 - * “no”:当前组件不可被无障碍辅助服务所识别 - * “no-hide-descendants”:当前组件及其所有子组件不可被无障碍辅助服务所识别 - */ - int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel)(ArkUI_AccessibilityElementInfo*, const char*) = - OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel"); - if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel is null, %{public}s", dlerror()); - } + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetCheckable -> true"; + } + // 判断当前节点(check box/radio button)是否checked/unchecked + if (IsNodeChecked(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetChecked)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetChecked"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetChecked); ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes"); + OH_ArkUI_AccessibilityElementInfoSetChecked(elementInfoFromList, true) ); - // 无障碍组,设置为true时表示该组件及其所有子组件为一整个可以选中的组件,无障碍服务将不再关注其子组件内容。默认值:false - int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup"); - if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup is null, %{public}s", dlerror()); - } + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetChecked -> true"; + } + // 判断当前节点组件是否可显示 + if (IsNodeVisible(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetVisible)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetVisible"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetVisible); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetVisible(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetVisible -> true"; + } + // 判断当前节点组件是否选中 + if (IsNodeSelected(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetSelected)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetSelected"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetSelected); + OH_ArkUI_AccessibilityElementInfoSetSelected(elementInfoFromList, true); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetSelected -> true"; + } + // 判断当前节点组件是否可滑动 + if (IsNodeScrollable(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetScrollable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetScrollable"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetScrollable); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetScrollable(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetScrollable -> true"; + } + // 判断当前节点组件是否可编辑(文本输入框) + if (IsTextField(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetEditable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetEditable"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetEditable); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetEditable(elementInfoFromList, true) + ); + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetEditable -> true"; + } + // 判断当前节点组件是否为滑动条 + if (IsSlider(flutterNode)) { + FML_DLOG(INFO) << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetRangeInfo -> true"; + } + // 判断当前节点组件是否支持长按 + if (IsNodeHasLongPress(flutterNode)) { + int32_t (*OH_ArkUI_AccessibilityElementInfoSetLongClickable)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetLongClickable"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetLongClickable); ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, false); + OH_ArkUI_AccessibilityElementInfoSetLongClickable(elementInfoFromList, true) + ); + FML_DLOG(INFO) + << "flutterNode.id=" << flutterNode.id + << " OH_ArkUI_AccessibilityElementInfoSetLongClickable -> true"; + } + + // 获取当前节点的组件类型 + std::string componentTypeName = GetNodeComponentType(flutterNode); + FML_DLOG(INFO) << "FlutterNodeToElementInfoById componentTypeName = " + << componentTypeName; + // flutter节点对应elementinfo所属的组件类型(如:root, button,text等) + int32_t (*OH_ArkUI_AccessibilityElementInfoSetComponentType)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetComponentType"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetComponentType); + if (elementId == 0) { + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, "root") + ); + } else { + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetComponentType(elementInfoFromList, + componentTypeName.c_str()) ); } + FML_DLOG(INFO) << "FlutterNodeToElementInfoById SetComponentType: " + << componentTypeName; + + /** + * 无障碍重要性,用于控制某个组件是否可被无障碍辅助服务所识别。支持的值为(默认值:“auto”): + * “auto”:根据组件不同会转换为“yes”或者“no” + * “yes”:当前组件可被无障碍辅助服务所识别 + * “no”:当前组件不可被无障碍辅助服务所识别 + * “no-hide-descendants”:当前组件及其所有子组件不可被无障碍辅助服务所识别 + */ + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel)(ArkUI_AccessibilityElementInfo*, const char*) = + OhosAccessibilityDDL::DLLoadSetElemStringFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityLevel(elementInfoFromList, "yes"); + ); + // 无障碍组,设置为true时表示该组件及其所有子组件为一整个可以选中的组件,无障碍服务将不再关注其子组件内容。默认值:false + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup); + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityGroup(elementInfoFromList, false); + ); } /** @@ -1247,29 +1149,26 @@ void OhosAccessibilityBridge::BuildArkUISemanticsTree( ArkUI_AccessibilityElementInfo* elementInfoFromList, ArkUI_AccessibilityElementInfoList* elementList) { - if (OHOS_API_VERSION >= 13) { - //配置root节点信息 - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - //获取flutter无障碍语义树的节点总数 - auto levelOrderTreeVec = GetLevelOrderTraversalTree(0); - int64_t elementInfoCount = levelOrderTreeVec.size(); - //创建并配置节点id >= 1的全部节点 - for (int64_t i = 1; i < elementInfoCount; i++) { - int64_t levelOrderId = levelOrderTreeVec[i]; - auto newNode = GetFlutterSemanticsNode(levelOrderId); - if (g_flutterSemanticsTree.count(newNode.id)) { - LOGE("BuildArkUISemanticsTree: GetFlutterSemanticsNode id=%{public}ld null", levelOrderId); - } - //当节点为隐藏状态时,自动规避 - auto* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = - OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); - if (OH_ArkUI_AddAndGetAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_AddAndGetAccessibilityElementInfo is null, %{public}s", dlerror()); - } - auto* newElementInfo = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); - //配置当前子节点信息 - FlutterNodeToElementInfoById(newElementInfo, levelOrderId); - } + if (OHOS_API_VERSION < 13) { return; } + //配置root节点信息 + FlutterNodeToElementInfoById(elementInfoFromList, elementId); + //获取flutter无障碍语义树的节点总数 + auto levelOrderTreeVec = GetLevelOrderTraversalTree(0); + int64_t elementInfoCount = levelOrderTreeVec.size(); + //创建并配置节点id >= 1的全部节点 + for (int64_t i = 1; i < elementInfoCount; i++) { + int64_t levelOrderId = levelOrderTreeVec[i]; + auto newNode = GetFlutterSemanticsNode(levelOrderId); + if (g_flutterSemanticsTree.count(newNode.id)) { + LOGE("BuildArkUISemanticsTree: GetFlutterSemanticsNode id=%{public}ld null", levelOrderId); + } + //当节点为隐藏状态时,自动规避 + auto* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = + OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AddAndGetAccessibilityElementInfo); + auto* newElementInfo = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + //配置当前子节点信息 + FlutterNodeToElementInfoById(newElementInfo, levelOrderId); } } @@ -1283,21 +1182,19 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( int32_t requestId, ArkUI_AccessibilityElementInfoList* elementList) { + if (OHOS_API_VERSION < 13) { return ARKUI_FAILED_CODE; } FML_DLOG(INFO) << "#### FindAccessibilityNodeInfosById input-params ####: elementId = " << elementId << " mode=" << mode << " requestId=" << requestId << " elementList= " << elementList; + CHECK_NULL_PTR_WITH_RET(elementList, FindAccessibilityNodeInfosById); if (g_flutterSemanticsTree.size() == 0) { FML_DLOG(INFO) << "FindAccessibilityNodeInfosById g_flutterSemanticsTree is null"; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; } - if (elementList == nullptr) { - FML_DLOG(INFO) << "FindAccessibilityNodeInfosById elementList is null"; - return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; - } - + // 获取当前对应id的flutter节点,若为空则返回错误编码 auto flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); if (!g_flutterSemanticsTree.count(flutterNode.id)) { @@ -1309,43 +1206,36 @@ int32_t OhosAccessibilityBridge::FindAccessibilityNodeInfosById( accessibilityFeatures_->SetAccessibleNavigation(true, native_shell_holder_id_); } - if (OHOS_API_VERSION >= 13) { - // 从elementinfolist中获取elementinfo - auto* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = - OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); - if (OH_ArkUI_AddAndGetAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_AddAndGetAccessibilityElementInfo is null, %{public}s", dlerror()); + // 从elementinfolist中获取elementinfo + auto* (*OH_ArkUI_AddAndGetAccessibilityElementInfo)(ArkUI_AccessibilityElementInfoList*) = + OhosAccessibilityDDL::DLLoadGetElemFunc("OH_ArkUI_AddAndGetAccessibilityElementInfo"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AddAndGetAccessibilityElementInfo); + auto* elementInfoFromList = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); + CHECK_NULL_PTR_WITH_RET(elementInfoFromList, OH_ArkUI_AddAndGetAccessibilityElementInfo); + + if (mode == ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { + /** Search for current nodes. (mode = 0) */ + BuildArkUISemanticsTree(elementId, elementInfoFromList, elementList); + } else if (mode ==ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS) { + /** Search for parent nodes. (mode = 1) */ + if (IsNodeVisible(flutterNode)) { + FlutterNodeToElementInfoById(elementInfoFromList, elementId); } - auto* elementInfoFromList = OH_ArkUI_AddAndGetAccessibilityElementInfo(elementList); - if (elementInfoFromList == nullptr) { - FML_DLOG(INFO) << "FindAccessibilityNodeInfosById elementInfoFromList is null"; - return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; + } else if (mode ==ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_SIBLINGS) { + /** Search for sibling nodes. (mode = 2) */ + if (IsNodeVisible(flutterNode)) { + FlutterNodeToElementInfoById(elementInfoFromList, elementId); } - - if (mode == ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CURRENT) { - /** Search for current nodes. (mode = 0) */ - BuildArkUISemanticsTree(elementId, elementInfoFromList, elementList); - } else if (mode ==ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_PREDECESSORS) { - /** Search for parent nodes. (mode = 1) */ - if (IsNodeVisible(flutterNode)) { - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - } - } else if (mode ==ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_SIBLINGS) { - /** Search for sibling nodes. (mode = 2) */ - if (IsNodeVisible(flutterNode)) { - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - } - } else if (mode ==ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CHILDREN) { - /** Search for child nodes at the next level. (mode = 4) */ - if (IsNodeVisible(flutterNode)) { - FlutterNodeToElementInfoById(elementInfoFromList, elementId); - } - } else if (mode ==ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_RECURSIVE_CHILDREN) { - /** Search for all child nodes. (mode = 8) */ - BuildArkUISemanticsTree(elementId, elementInfoFromList, elementList); - } else { + } else if (mode ==ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_CHILDREN) { + /** Search for child nodes at the next level. (mode = 4) */ + if (IsNodeVisible(flutterNode)) { FlutterNodeToElementInfoById(elementInfoFromList, elementId); } + } else if (mode ==ArkUI_AccessibilitySearchMode::ARKUI_ACCESSIBILITY_NATIVE_SEARCH_MODE_PREFETCH_RECURSIVE_CHILDREN) { + /** Search for all child nodes. (mode = 8) */ + BuildArkUISemanticsTree(elementId, elementInfoFromList, elementList); + } else { + FlutterNodeToElementInfoById(elementInfoFromList, elementId); } FML_DLOG(INFO) << "--- FindAccessibilityNodeInfosById is end ---"; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; @@ -1572,29 +1462,26 @@ void OhosAccessibilityBridge::PerformSetText( ArkUI_Accessibility_ActionType action, ArkUI_AccessibilityActionArguments* actionArguments) { - if (OHOS_API_VERSION >= 13) { - int32_t (*OH_ArkUI_FindAccessibilityActionArgumentByKey)(ArkUI_AccessibilityActionArguments*, const char*, char**) = - OhosAccessibilityDDL::DLLoadGetFindActionArgs("OH_ArkUI_FindAccessibilityActionArgumentByKey"); - if (OH_ArkUI_FindAccessibilityActionArgumentByKey == nullptr) { - LOGE("OH_ArkUI_FindAccessibilityActionArgumentByKey is null, %{public}s", dlerror()); - } - const char* key_setText = "setText"; - const char* valueStr = flutterNode.value.c_str(); - char* newValue = strdup(valueStr); - char** value = &newValue; - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key_setText, value)); - if (newValue == nullptr) { - LOGE("PerformSetText -> OH_ArkUI_FindAccessibilityActionArgumentByKey get null value"); - } - auto flutterSetTextAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(flutterNode.id, - flutterSetTextAction, - fml::MallocMapping::Copy(newValue, strlen(newValue))); - flutterNode.value = newValue; - flutterNode.valueAttributes = {}; - LOGI("ExecuteAccessibilityAction -> action: set text(%{public}d), newText=%{public}s", action, newValue); - } + if (OHOS_API_VERSION < 13) { return; } + int32_t (*OH_ArkUI_FindAccessibilityActionArgumentByKey)(ArkUI_AccessibilityActionArguments*, const char*, char**) = + OhosAccessibilityDDL::DLLoadGetFindActionArgs("OH_ArkUI_FindAccessibilityActionArgumentByKey"); + CHECK_DLL_NULL_PTR(OH_ArkUI_FindAccessibilityActionArgumentByKey); + + const char* key_setText = "setText"; + const char* valueStr = flutterNode.value.c_str(); + char* newValue = strdup(valueStr); + char** value = &newValue; + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key_setText, value)); + CHECK_NULL_PTR(newValue, PerformSetText); + + auto flutterSetTextAction = ArkuiActionsToFlutterActions(action); + DispatchSemanticsAction(flutterNode.id, + flutterSetTextAction, + fml::MallocMapping::Copy(newValue, strlen(newValue))); + flutterNode.value = newValue; + flutterNode.valueAttributes = {}; + LOGI("ExecuteAccessibilityAction -> action: set text(%{public}d), newText=%{public}s", action, newValue); } /** @@ -1606,7 +1493,7 @@ void OhosAccessibilityBridge::PerformSelectText( ArkUI_AccessibilityActionArguments* actionArguments) { FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: select text(" << action << ")"; - return; + } /** @@ -1657,12 +1544,7 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( << elementId << " action=" << action << " requestId=" << requestId << " *actionArguments=" << actionArguments; - - if (actionArguments == nullptr) { - FML_DLOG(ERROR) << "OhosAccessibilityBridge::ExecuteAccessibilityAction " - "actionArguments = null"; - return ARKUI_ACCESSIBILITY_NATIVE_RESULT_FAILED; - } + CHECK_NULL_PTR_WITH_RET(actionArguments, ExecuteAccessibilityAction); // 获取当前elementid对应的flutter语义节点 auto flutterNode = GetFlutterSemanticsNode(static_cast(elementId)); @@ -1859,95 +1741,72 @@ void OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent( int64_t elementId, ArkUI_AccessibilityEventType eventType) { - if (provider_ == nullptr) { - FML_DLOG(ERROR) << "Flutter_SendAccessibilityAsyncEvent " - "AccessibilityProvider = nullptr"; - return; + if (OHOS_API_VERSION < 13) { return; } + + CHECK_NULL_PTR(provider_, Flutter_SendAccessibilityAsyncEvent); + + // 1.创建eventInfo对象 + auto* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = + OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); + CHECK_DLL_NULL_PTR(OH_ArkUI_CreateAccessibilityEventInfo); + auto* eventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); + CHECK_NULL_PTR(eventInfo, Flutter_SendAccessibilityAsyncEvent); + + // 2.创建的elementinfo并根据对应id的flutternode进行属性初始化 + ArkUI_AccessibilityElementInfo* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = + OhosAccessibilityDDL::DLLoadCreateElemInfoFunc("OH_ArkUI_CreateAccessibilityElementInfo"); + CHECK_DLL_NULL_PTR(OH_ArkUI_CreateAccessibilityElementInfo); + ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); + FlutterNodeToElementInfoById(_elementInfo, elementId); + + // 若为获焦事件,则设置当前elementinfo获焦 + int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused)(ArkUI_AccessibilityElementInfo*, bool) = + OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused); + if (eventType == ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED) { + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused(_elementInfo, true) + ); } - if (OHOS_API_VERSION >= 13) { - // 1.创建eventInfo对象 - ArkUI_AccessibilityEventInfo* (*OH_ArkUI_CreateAccessibilityEventInfo)(void) = - OhosAccessibilityDDL::DLLoadCreateEventInfoFunc("OH_ArkUI_CreateAccessibilityEventInfo"); - if (OH_ArkUI_CreateAccessibilityEventInfo == nullptr) { - LOGE("OH_ArkUI_CreateAccessibilityEventInfo is null, %{public}s", dlerror()); - } - ArkUI_AccessibilityEventInfo* eventInfo = OH_ArkUI_CreateAccessibilityEventInfo(); - if (eventInfo == nullptr) { - FML_DLOG(ERROR) << "Flutter_SendAccessibilityAsyncEvent " - "OH_ArkUI_CreateAccessibilityEventInfo eventInfo = null"; - return; - } - // 2.创建的elementinfo并根据对应id的flutternode进行属性初始化 - ArkUI_AccessibilityElementInfo* (*OH_ArkUI_CreateAccessibilityElementInfo)(void) = - OhosAccessibilityDDL::DLLoadCreateElemInfoFunc("OH_ArkUI_CreateAccessibilityElementInfo"); - if (OH_ArkUI_CreateAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_CreateAccessibilityElementInfo is null, %{public}s", dlerror()); - } - ArkUI_AccessibilityElementInfo* _elementInfo = OH_ArkUI_CreateAccessibilityElementInfo(); - FlutterNodeToElementInfoById(_elementInfo, elementId); - - // 若为获焦事件,则设置当前elementinfo获焦 - int32_t (*OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused)(ArkUI_AccessibilityElementInfo*, bool) = - OhosAccessibilityDDL::DLLoadSetElemBoolFunc("OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused"); - if (OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused == nullptr) { - LOGE("OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused is null, %{public}s", dlerror()); - } - if (eventType == ArkUI_AccessibilityEventType::ARKUI_ACCESSIBILITY_NATIVE_EVENT_TYPE_ACCESSIBILITY_FOCUSED) { - ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_AccessibilityElementInfoSetAccessibilityFocused(_elementInfo, true) - ); - } + // 3.设置发送事件,如配置获焦、失焦、点击、滑动事件 + int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = + OhosAccessibilityDDL::DLLoadSetEventFunc("OH_ArkUI_AccessibilityEventSetEventType"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityEventSetEventType); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityEventSetEventType(eventInfo, eventType)); - // 3.设置发送事件,如配置获焦、失焦、点击、滑动事件 - int32_t (*OH_ArkUI_AccessibilityEventSetEventType)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityEventType) = - OhosAccessibilityDDL::DLLoadSetEventFunc("OH_ArkUI_AccessibilityEventSetEventType"); - if (OH_ArkUI_AccessibilityEventSetEventType == nullptr) { - LOGE("OH_ArkUI_AccessibilityEventSetEventType is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityEventSetEventType(eventInfo, eventType)); - - // 4.将eventinfo事件和当前elementinfo进行绑定 - int32_t (*OH_ArkUI_AccessibilityEventSetElementInfo)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityElementInfo*) = - OhosAccessibilityDDL::DLLoadSetEventElemFunc("OH_ArkUI_AccessibilityEventSetElementInfo"); - if (OH_ArkUI_AccessibilityEventSetElementInfo == nullptr) { - LOGE("OH_ArkUI_AccessibilityEventSetElementInfo is null, %{public}s", dlerror()); - } - ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityEventSetElementInfo(eventInfo, _elementInfo)); - - // 5.调用接口发送到ohos侧 - auto callback = [](int32_t errorCode) { - FML_DLOG(INFO) - << "Flutter_SendAccessibilityAsyncEvent callback-> errorCode =" - << errorCode; - }; - - // 6.发送event到OH侧 - void (*OH_ArkUI_SendAccessibilityAsyncEvent)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*callback)(int32_t)) = - OhosAccessibilityDDL::DLLoadSendAsyncEventFunc("OH_ArkUI_SendAccessibilityAsyncEvent"); - if (OH_ArkUI_SendAccessibilityAsyncEvent == nullptr) { - LOGE("OH_ArkUI_SendAccessibilityAsyncEvent is null, %{public}s", dlerror()); - } - OH_ArkUI_SendAccessibilityAsyncEvent(provider_, eventInfo, callback); - - // 7.销毁新创建的elementinfo, eventinfo - void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = - OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); - if (OH_ArkUI_DestoryAccessibilityElementInfo == nullptr) { - LOGE("OH_ArkUI_DestoryAccessibilityElementInfo is null, %{public}s", dlerror()); - } - OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); - _elementInfo = nullptr; - - void (*OH_ArkUI_DestoryAccessibilityEventInfo)(ArkUI_AccessibilityEventInfo*) = - OhosAccessibilityDDL::DLLoadDestroyEventFunc("OH_ArkUI_DestoryAccessibilityEventInfo"); - if (OH_ArkUI_DestoryAccessibilityEventInfo == nullptr) { - LOGE("OH_ArkUI_DestoryAccessibilityEventInfo is null, %{public}s", dlerror()); - } - OH_ArkUI_DestoryAccessibilityEventInfo(eventInfo); - eventInfo = nullptr; - } + // 4.将eventinfo事件和当前elementinfo进行绑定 + int32_t (*OH_ArkUI_AccessibilityEventSetElementInfo)(ArkUI_AccessibilityEventInfo*, ArkUI_AccessibilityElementInfo*) = + OhosAccessibilityDDL::DLLoadSetEventElemFunc("OH_ArkUI_AccessibilityEventSetElementInfo"); + CHECK_DLL_NULL_PTR(OH_ArkUI_AccessibilityEventSetElementInfo); + ARKUI_ACCESSIBILITY_CALL_CHECK(OH_ArkUI_AccessibilityEventSetElementInfo(eventInfo, _elementInfo)); + // 5.调用接口发送到ohos侧 + auto callback = [](int32_t errorCode) { + FML_DLOG(INFO) + << "Flutter_SendAccessibilityAsyncEvent callback-> errorCode =" + << errorCode; + }; + + // 6.发送event到OH侧 + void (*OH_ArkUI_SendAccessibilityAsyncEvent)(ArkUI_AccessibilityProvider*, ArkUI_AccessibilityEventInfo*, void (*callback)(int32_t)) = + OhosAccessibilityDDL::DLLoadSendAsyncEventFunc("OH_ArkUI_SendAccessibilityAsyncEvent"); + CHECK_DLL_NULL_PTR(OH_ArkUI_SendAccessibilityAsyncEvent); + OH_ArkUI_SendAccessibilityAsyncEvent(provider_, eventInfo, callback); + + // 7.销毁新创建的elementinfo, eventinfo + void (*OH_ArkUI_DestoryAccessibilityElementInfo)(ArkUI_AccessibilityElementInfo*) = + OhosAccessibilityDDL::DLLoadDestroyElemFunc("OH_ArkUI_DestoryAccessibilityElementInfo"); + CHECK_DLL_NULL_PTR(OH_ArkUI_DestoryAccessibilityElementInfo); + OH_ArkUI_DestoryAccessibilityElementInfo(_elementInfo); + _elementInfo = nullptr; + + void (*OH_ArkUI_DestoryAccessibilityEventInfo)(ArkUI_AccessibilityEventInfo*) = + OhosAccessibilityDDL::DLLoadDestroyEventFunc("OH_ArkUI_DestoryAccessibilityEventInfo"); + CHECK_DLL_NULL_PTR(OH_ArkUI_DestoryAccessibilityEventInfo); + OH_ArkUI_DestoryAccessibilityEventInfo(eventInfo); + eventInfo = nullptr; + FML_DLOG(INFO) << "OhosAccessibilityBridge::Flutter_SendAccessibilityAsyncEvent is end"; return; } diff --git a/shell/platform/ohos/utils/ddl_utils.h b/shell/platform/ohos/utils/ddl_utils.h index 5ddbb0e954..19e5e5fb18 100644 --- a/shell/platform/ohos/utils/ddl_utils.h +++ b/shell/platform/ohos/utils/ddl_utils.h @@ -21,5 +21,6 @@ using LIBHANDLE = void*; #define LOAD_LIB(libPath) dlopen(libPath, RTLD_LAZY|RTLD_LOCAL) #define CLOSE_LIB(libHandle) dlclose(libHandle) #define LOAD_SYM(libHandle, symbol) dlsym(libHandle, symbol) +#define LOAD_ERROR() dlerror() #endif // FOUNDATION_ACE_INTERFACE_INNERKITS_ACE_UTILS_H -- Gitee From f34b812f366ec494b6d29f502f18623d382138d7 Mon Sep 17 00:00:00 2001 From: zjxi Date: Tue, 17 Dec 2024 21:10:05 +0800 Subject: [PATCH 13/15] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0selecttext?= =?UTF-8?q?=E5=8A=A8=E4=BD=9C=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9Emap=E5=BA=8F=E5=88=97=E5=8C=96=E5=AD=97?= =?UTF-8?q?=E8=8A=82=E6=95=B0=E7=BB=84=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 | 60 +++++++++++++++---- .../accessibility/ohos_accessibility_bridge.h | 4 ++ shell/platform/ohos/utils/ohos_utils.cpp | 38 ++++++++++++ shell/platform/ohos/utils/ohos_utils.h | 7 ++- 4 files changed, 95 insertions(+), 14 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index ba0882e42c..e76880fc77 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -1467,25 +1467,22 @@ void OhosAccessibilityBridge::PerformSetText( OhosAccessibilityDDL::DLLoadGetFindActionArgs("OH_ArkUI_FindAccessibilityActionArgumentByKey"); CHECK_DLL_NULL_PTR(OH_ArkUI_FindAccessibilityActionArgumentByKey); - const char* key_setText = "setText"; - const char* valueStr = flutterNode.value.c_str(); - char* newValue = strdup(valueStr); - char** value = &newValue; + char* newText; ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, key_setText, value)); - CHECK_NULL_PTR(newValue, PerformSetText); + OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, ARKUI_ACTION_ARG_SET_TEXT, &newText)); + CHECK_NULL_PTR(newText, PerformSetText); auto flutterSetTextAction = ArkuiActionsToFlutterActions(action); - DispatchSemanticsAction(flutterNode.id, - flutterSetTextAction, - fml::MallocMapping::Copy(newValue, strlen(newValue))); - flutterNode.value = newValue; + DispatchSemanticsAction(flutterNode.id, + flutterSetTextAction, + fml::MallocMapping::Copy(newText, strlen(newText))); + flutterNode.value = newText; flutterNode.valueAttributes = {}; - LOGI("ExecuteAccessibilityAction -> action: set text(%{public}d), newText=%{public}s", action, newValue); + LOGI("ExecuteAccessibilityAction -> action: set text(%{public}d), newText=%{public}s", action, newText); } /** - * perform cursor position setting in accessibility status + * perform select text (from base to extent) in accessibility status */ void OhosAccessibilityBridge::PerformSelectText( SemanticsNodeExtent flutterNode, @@ -1493,7 +1490,44 @@ void OhosAccessibilityBridge::PerformSelectText( ArkUI_AccessibilityActionArguments* actionArguments) { FML_DLOG(INFO) << "ExecuteAccessibilityAction -> action: select text(" << action << ")"; - + int32_t (*OH_ArkUI_FindAccessibilityActionArgumentByKey)(ArkUI_AccessibilityActionArguments*, const char*, char**) = + OhosAccessibilityDDL::DLLoadGetFindActionArgs("OH_ArkUI_FindAccessibilityActionArgumentByKey"); + CHECK_DLL_NULL_PTR(OH_ArkUI_FindAccessibilityActionArgumentByKey); + + auto flutterSelectTextAction = ArkuiActionsToFlutterActions(action); + + char* textSelectBase; + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, ARKUI_ACTION_ARG_SELECT_TEXT_START, &textSelectBase) + ); + CHECK_NULL_PTR(textSelectBase, PerformSelectText); + + char* textSelectExtent; + ARKUI_ACCESSIBILITY_CALL_CHECK( + OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, ARKUI_ACTION_ARG_SELECT_TEXT_END, &textSelectExtent) + ); + CHECK_NULL_PTR(textSelectExtent, PerformSelectText); + + std::map selectionMap; + bool hasSelected = actionArguments != nullptr && + textSelectBase != nullptr && + textSelectExtent != nullptr; + if (hasSelected) { + int32_t base; + int32_t extent; + std::memcpy(&base, textSelectBase, sizeof(base)); + std::memcpy(&extent, textSelectExtent, sizeof(extent)); + selectionMap.insert({ARKUI_ACTION_ARG_SELECT_TEXT_START, base}); + selectionMap.insert({ARKUI_ACTION_ARG_SELECT_TEXT_END, extent}); + } else { + selectionMap.insert({ARKUI_ACTION_ARG_SELECT_TEXT_START, flutterNode.textSelectionBase}); + selectionMap.insert({ARKUI_ACTION_ARG_SELECT_TEXT_END, flutterNode.textSelectionExtent}); + } + // serialize map to byte vector + std::vector encodedData = OHOSUtils::SerializeStringIntMap(selectionMap); + DispatchSemanticsAction(flutterNode.id, + flutterSelectTextAction, + fml::MallocMapping::Copy(encodedData.data(), encodedData.size() * sizeof(uint8_t))); } /** diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h index 39d14c80eb..5c135ada61 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.h @@ -175,6 +175,10 @@ private: constexpr static const double SCROLL_EXTENT_FOR_INFINITY = 100000.0; constexpr static const double SCROLL_POSITION_CAP_FOR_INFINITY = 70000.0; + const char* ARKUI_ACTION_ARG_SET_TEXT = "setText"; + const char* ARKUI_ACTION_ARG_SELECT_TEXT_START = "selectTextBegin"; + const char* ARKUI_ACTION_ARG_SELECT_TEXT_END = "selectTextEnd"; + const std::string OTHER_WIDGET_NAME = "View"; const std::string TEXT_WIDGET_NAME = "Text"; const std::string EDIT_TEXT_WIDGET_NAME = "TextInput"; diff --git a/shell/platform/ohos/utils/ohos_utils.cpp b/shell/platform/ohos/utils/ohos_utils.cpp index 23813a7528..96a2e84876 100644 --- a/shell/platform/ohos/utils/ohos_utils.cpp +++ b/shell/platform/ohos/utils/ohos_utils.cpp @@ -27,4 +27,42 @@ bool OHOSUtils::Contains(const std::string source, return source.find(target) != std::string::npos; } +/** + * 将string序列化为uint8字节数组 + */ +void OHOSUtils::SerializeString(const std::string& str, std::vector& buffer) +{ + // store the length of the string as a uint8_t + uint32_t length = str.size(); + buffer.insert(buffer.end(), + reinterpret_cast(&length), + reinterpret_cast(&length) + sizeof(length)); + // store the actual string data + buffer.insert(buffer.end(), str.begin(), str.end()); +} + +/** + * 将map序列化为uint8字节数组 + */ +std::vector OHOSUtils::SerializeStringIntMap(const std::map& mp) +{ + std::vector buffer; + + // Store the number of elements in the map + uint32_t mapSize = mp.size(); + buffer.insert(buffer.end(), + reinterpret_cast(&mapSize), + reinterpret_cast(&mapSize) + sizeof(mapSize)); + + // Iterate over the map and serialize each key-value pair + for (const auto& it : mp) { + SerializeString(it.first, buffer); + buffer.insert(buffer.end(), + reinterpret_cast(&it.second), + reinterpret_cast(&it.second) + sizeof(it.second)); + } + + return buffer; +} + } \ No newline at end of file diff --git a/shell/platform/ohos/utils/ohos_utils.h b/shell/platform/ohos/utils/ohos_utils.h index f76e79bef3..49686b94e9 100644 --- a/shell/platform/ohos/utils/ohos_utils.h +++ b/shell/platform/ohos/utils/ohos_utils.h @@ -16,7 +16,10 @@ #ifndef OHOS_UTILS_H #define OHOS_UTILS_H #include - +#include +#include +#include +#include namespace flutter { class OHOSUtils { @@ -25,6 +28,8 @@ public: ~OHOSUtils(); static bool Contains(const std::string source, const std::string target); + static void SerializeString(const std::string& str, std::vector& buffer); + static std::vector SerializeStringIntMap(const std::map& mp); }; } -- Gitee From 718054325f87377e49ababd3084824d33bdfd39f Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 18 Dec 2024 10:54:31 +0800 Subject: [PATCH 14/15] =?UTF-8?q?refactor:=E6=9B=BF=E6=8D=A2=E4=B8=8D?= =?UTF-8?q?=E5=AE=89=E5=85=A8memcpy=E5=87=BD=E6=95=B0=EF=BC=8C=E4=BD=BF?= =?UTF-8?q?=E7=94=A8strol=E6=96=B9=E5=BC=8F=E8=BF=9B=E8=A1=8C=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E4=B8=B2=E5=92=8C=E6=95=B0=E5=AD=97=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=EF=BC=8C=E5=B9=B6=E6=89=8B=E5=8A=A8=E5=A4=84=E7=90=86=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 10 +++++---- shell/platform/ohos/utils/ohos_utils.cpp | 22 +++++++++++++++++-- shell/platform/ohos/utils/ohos_utils.h | 2 ++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index e76880fc77..e81ecc6946 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -1498,13 +1498,15 @@ void OhosAccessibilityBridge::PerformSelectText( char* textSelectBase; ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, ARKUI_ACTION_ARG_SELECT_TEXT_START, &textSelectBase) + OH_ArkUI_FindAccessibilityActionArgumentByKey( + actionArguments, ARKUI_ACTION_ARG_SELECT_TEXT_START, &textSelectBase) ); CHECK_NULL_PTR(textSelectBase, PerformSelectText); char* textSelectExtent; ARKUI_ACCESSIBILITY_CALL_CHECK( - OH_ArkUI_FindAccessibilityActionArgumentByKey(actionArguments, ARKUI_ACTION_ARG_SELECT_TEXT_END, &textSelectExtent) + OH_ArkUI_FindAccessibilityActionArgumentByKey( + actionArguments, ARKUI_ACTION_ARG_SELECT_TEXT_END, &textSelectExtent) ); CHECK_NULL_PTR(textSelectExtent, PerformSelectText); @@ -1515,8 +1517,8 @@ void OhosAccessibilityBridge::PerformSelectText( if (hasSelected) { int32_t base; int32_t extent; - std::memcpy(&base, textSelectBase, sizeof(base)); - std::memcpy(&extent, textSelectExtent, sizeof(extent)); + OHOSUtils::CharArrayToInt32(textSelectBase, base); + OHOSUtils::CharArrayToInt32(textSelectBase, extent); selectionMap.insert({ARKUI_ACTION_ARG_SELECT_TEXT_START, base}); selectionMap.insert({ARKUI_ACTION_ARG_SELECT_TEXT_END, extent}); } else { diff --git a/shell/platform/ohos/utils/ohos_utils.cpp b/shell/platform/ohos/utils/ohos_utils.cpp index 96a2e84876..1d4058f086 100644 --- a/shell/platform/ohos/utils/ohos_utils.cpp +++ b/shell/platform/ohos/utils/ohos_utils.cpp @@ -34,8 +34,8 @@ void OHOSUtils::SerializeString(const std::string& str, std::vector& bu { // store the length of the string as a uint8_t uint32_t length = str.size(); - buffer.insert(buffer.end(), - reinterpret_cast(&length), + buffer.insert(buffer.end(), + reinterpret_cast(&length), reinterpret_cast(&length) + sizeof(length)); // store the actual string data buffer.insert(buffer.end(), str.begin(), str.end()); @@ -65,4 +65,22 @@ std::vector OHOSUtils::SerializeStringIntMap(const std::map(num); + LOGD("The int32_t value is: %{public}d", target); + } else { + target = 0; + LOGE("Conversion error, non-convertible part: %{public}s", end); + } +} + } \ No newline at end of file diff --git a/shell/platform/ohos/utils/ohos_utils.h b/shell/platform/ohos/utils/ohos_utils.h index 49686b94e9..e9d6b7b683 100644 --- a/shell/platform/ohos/utils/ohos_utils.h +++ b/shell/platform/ohos/utils/ohos_utils.h @@ -20,6 +20,7 @@ #include #include #include +#include "flutter/shell/platform/ohos/ohos_logging.h" namespace flutter { class OHOSUtils { @@ -30,6 +31,7 @@ public: static bool Contains(const std::string source, const std::string target); static void SerializeString(const std::string& str, std::vector& buffer); static std::vector SerializeStringIntMap(const std::map& mp); + static void CharArrayToInt32(const char* str, int32_t& target); }; } -- Gitee From 48281cf724f4cc5f0865bce7a8b5db9417ff23f0 Mon Sep 17 00:00:00 2001 From: zjxi Date: Wed, 18 Dec 2024 11:06:54 +0800 Subject: [PATCH 15/15] =?UTF-8?q?=E5=88=A0=E9=99=A4switch-case=E4=B8=AD?= =?UTF-8?q?=E5=A4=9A=E4=BD=99=E8=8A=B1=E6=8B=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zjxi --- .../ohos_accessibility_bridge.cpp | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp index e81ecc6946..48e06cb30b 100644 --- a/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp +++ b/shell/platform/ohos/accessibility/ohos_accessibility_bridge.cpp @@ -1597,76 +1597,75 @@ int32_t OhosAccessibilityBridge::ExecuteAccessibilityAction( // 根据当前elementid和无障碍动作类型,发送无障碍事件 switch (action) { /** Response to a click. 16 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: { + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLICK: PerformClickAction(elementId, action, flutterNode); 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: PerformLongClickAction(elementId, action, flutterNode); break; - } + /** Accessibility focus acquisition. 64 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: { + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_GAIN_ACCESSIBILITY_FOCUS: PerformGainFocusnAction(elementId, action, flutterNode); break; - } + /** Accessibility focus clearance. 128 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: { + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CLEAR_ACCESSIBILITY_FOCUS: PerformClearFocusAction(elementId, action, flutterNode); 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: PerformScrollUpAction(elementId, action, flutterNode); break; - } + /** Backward scroll action. 512 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: { + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SCROLL_BACKWARD: PerformScrollDownAction(elementId, action, flutterNode); break; - } + /** Copy action for text content. 1024 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: { + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_COPY: PerformClipboardAction(elementId, action); break; - } + /** Paste action for text content. 2048 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE: { + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_PASTE: PerformClipboardAction(elementId, action); break; - } + /** Cut action for text content. 4096 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: { + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_CUT: PerformClipboardAction(elementId, action); 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: { + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SELECT_TEXT: PerformSelectText(flutterNode, action, actionArguments); break; - } + /** Text content setting action. 16384 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: { + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_TEXT: PerformSetText(flutterNode, action, actionArguments); break; - } + /** Cursor position setting action. 1048576 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION: { + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_SET_CURSOR_POSITION: PerformSetCursorPosition(flutterNode, action, actionArguments); break; - } + /** Invalid action. 0 */ - case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID: { + case ArkUI_Accessibility_ActionType::ARKUI_ACCESSIBILITY_NATIVE_ACTION_TYPE_INVALID: PerformInvalidAction(elementId, action, flutterNode); break; - } - default: { + + default: /** custom semantics action */ PerformCustomAction(flutterNode, action, actionArguments); - } } FML_DLOG(INFO) << "--- ExecuteAccessibilityAction is end ---"; return ARKUI_ACCESSIBILITY_NATIVE_RESULT_SUCCESSFUL; -- Gitee