* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* 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 "accessibility_event_manager.h"
#include <map>
#include "core/accessibility/accessibility_manager.h"
#include "core/common/container.h"
#include "core/pipeline_ng/pipeline_context.h"
#include "frameworks/bridge/common/accessibility/accessibility_node_manager.h"
namespace OHOS::Ace::Framework {
AccessibilityEventType ConvertEventType(const std::string& type)
{
static const std::map<std::string, AccessibilityEventType> typeMap = {
{ "accessibilityFocus", AccessibilityEventType::ACCESSIBILITY_FOCUSED },
{ "accessibilityFocusClear", AccessibilityEventType::ACCESSIBILITY_FOCUS_CLEARED },
{ "click", AccessibilityEventType::CLICK },
{ "longClick", AccessibilityEventType::LONG_PRESS },
{ "select", AccessibilityEventType::SELECTED },
{ "hoverEnter", AccessibilityEventType::HOVER_ENTER_EVENT },
{ "hoverExit", AccessibilityEventType::HOVER_EXIT_EVENT },
{ "textUpdate", AccessibilityEventType::TEXT_CHANGE },
{ "textSelectionUpdate", AccessibilityEventType::TEXT_SELECTION_UPDATE },
{ "scroll", AccessibilityEventType::SCROLL_START },
{ "requestFocusForAccessibility", AccessibilityEventType::REQUEST_FOCUS },
{ "announceForAccessibility", AccessibilityEventType::ANNOUNCE_FOR_ACCESSIBILITY },
{ "requestFocusForAccessibilityNotInterrupt", AccessibilityEventType::REQUEST_FOCUS_FOR_ACCESSIBILITY_NOT_INTERRUPT },
{ "announceForAccessibilityNotInterrupt", AccessibilityEventType::ANNOUNCE_FOR_ACCESSIBILITY_NOT_INTERRUPT },
{ "scrolling", AccessibilityEventType::SCROLLING_EVENT },
};
auto it = typeMap.find(type);
if (it != typeMap.end()) {
return it->second;
}
return AccessibilityEventType::UNKNOWN;
}
int32_t GetID(const RefPtr<NG::UINode>& node, const std::string& customId)
{
if (!node) {
return -1;
}
if (node->GetInspectorId().value_or("") == customId) {
return node->GetAccessibilityId();
}
const auto& children = node->GetChildren();
for (auto& child : children) {
int32_t nodeId = GetID(child, customId);
if (nodeId != -1) {
return nodeId;
}
}
return -1;
}
int32_t ConvertCustomId(const std::string& customId, uint32_t windowId)
{
auto container = Container::GetByWindowId(windowId);
if (!container) {
return -1;
}
auto context = container->GetPipelineContext();
auto pipelineContext = AceType::DynamicCast<NG::PipelineContext>(context);
if (!pipelineContext) {
return -1;
}
auto root = pipelineContext->GetRootElement();
return GetID(root, customId);
}
WindowUpdateType ConvertWindowUpdateType(const std::string& type)
{
static const std::map<std::string, WindowUpdateType> typeMap = {
{ "add", WindowUpdateType::WINDOW_UPDATE_ADDED },
{ "remove", WindowUpdateType::WINDOW_UPDATE_REMOVED },
{ "bounds", WindowUpdateType::WINDOW_UPDATE_BOUNDS },
{ "active", WindowUpdateType::WINDOW_UPDATE_ACTIVE },
{ "focus", WindowUpdateType::WINDOW_UPDATE_FOCUSED },
};
auto it = typeMap.find(type);
if (it != typeMap.end()) {
return it->second;
}
return WindowUpdateType::WINDOW_UPDATE_INVALID;
}
void AccessibilityEventManager::SendEventInfo(const AccessibilityEventInfo& event)
{
auto nodeManager = AccessibilityNodeManager::Create();
if (nodeManager) {
auto container = Container::GetActive();
if (!container) {
return;
}
auto pipelineContext = container->GetPipelineContext();
if (!pipelineContext) {
return;
}
auto windowId = pipelineContext->GetWindowId();
AccessibilityEvent accessibilityEvent;
accessibilityEvent.type = ConvertEventType(event.type);
accessibilityEvent.windowChangeTypes = ConvertWindowUpdateType(event.windowUpdateType);
accessibilityEvent.componentType = event.componentType;
accessibilityEvent.windowId = windowId;
accessibilityEvent.latestContent = event.lastContent;
accessibilityEvent.startIndex = event.beginIndex;
accessibilityEvent.currentItemIndex = event.currentIndex;
accessibilityEvent.endIndex = event.endIndex;
accessibilityEvent.itemCount = event.itemCount;
accessibilityEvent.textAnnouncedForAccessibility = event.textAnnouncedForAccessibility.empty()
? event.textResourceAnnouncedForAccessibility
: event.textAnnouncedForAccessibility;
accessibilityEvent.stackNodeId = event.elementId;
accessibilityEvent.nodeId = ConvertCustomId(event.customId,windowId);
nodeManager->SendAccessibilityAsyncEvent(accessibilityEvent);
}
}
}