// Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "flutter_platform_node_delegate.h" #include #include "flutter/third_party/accessibility/ax/ax_action_data.h" #include "flutter/third_party/accessibility/gfx/geometry/rect_conversions.h" namespace flutter { FlutterPlatformNodeDelegate::FlutterPlatformNodeDelegate() = default; FlutterPlatformNodeDelegate::~FlutterPlatformNodeDelegate() = default; void FlutterPlatformNodeDelegate::Init(std::weak_ptr bridge, ui::AXNode* node) { bridge_ = std::move(bridge); ax_node_ = node; } ui::AXNode* FlutterPlatformNodeDelegate::GetAXNode() const { return ax_node_; } bool FlutterPlatformNodeDelegate::AccessibilityPerformAction( const ui::AXActionData& data) { AccessibilityNodeId target = ax_node_->id(); auto bridge_ptr = bridge_.lock(); BASE_DCHECK(bridge_ptr); switch (data.action) { case ax::mojom::Action::kDoDefault: bridge_ptr->DispatchAccessibilityAction( target, FlutterSemanticsAction::kFlutterSemanticsActionTap, {}); return true; case ax::mojom::Action::kFocus: bridge_ptr->SetLastFocusedId(target); bridge_ptr->DispatchAccessibilityAction( target, FlutterSemanticsAction:: kFlutterSemanticsActionDidGainAccessibilityFocus, {}); return true; case ax::mojom::Action::kScrollToMakeVisible: bridge_ptr->DispatchAccessibilityAction( target, FlutterSemanticsAction::kFlutterSemanticsActionShowOnScreen, {}); return true; // TODO(chunhtai): support more actions. default: return false; } return false; } const ui::AXNodeData& FlutterPlatformNodeDelegate::GetData() const { return ax_node_->data(); } gfx::NativeViewAccessible FlutterPlatformNodeDelegate::GetParent() { if (!ax_node_->parent()) { return nullptr; } auto bridge_ptr = bridge_.lock(); BASE_DCHECK(bridge_ptr); return bridge_ptr->GetNativeAccessibleFromId(ax_node_->parent()->id()); } gfx::NativeViewAccessible FlutterPlatformNodeDelegate::GetFocus() { auto bridge_ptr = bridge_.lock(); BASE_DCHECK(bridge_ptr); AccessibilityNodeId last_focused = bridge_ptr->GetLastFocusedId(); if (last_focused == ui::AXNode::kInvalidAXID) { return nullptr; } return bridge_ptr->GetNativeAccessibleFromId(last_focused); } int FlutterPlatformNodeDelegate::GetChildCount() const { return static_cast(ax_node_->GetUnignoredChildCount()); } gfx::NativeViewAccessible FlutterPlatformNodeDelegate::ChildAtIndex(int index) { auto bridge_ptr = bridge_.lock(); BASE_DCHECK(bridge_ptr); AccessibilityNodeId child = ax_node_->GetUnignoredChildAtIndex(index)->id(); return bridge_ptr->GetNativeAccessibleFromId(child); } gfx::Rect FlutterPlatformNodeDelegate::GetBoundsRect( const ui::AXCoordinateSystem coordinate_system, const ui::AXClippingBehavior clipping_behavior, ui::AXOffscreenResult* offscreen_result) const { auto bridge_ptr = bridge_.lock(); BASE_DCHECK(bridge_ptr); // TODO(chunhtai): We need to apply screen dpr in here. // https://github.com/flutter/flutter/issues/74283 const bool clip_bounds = clipping_behavior == ui::AXClippingBehavior::kClipped; bool offscreen = false; gfx::RectF bounds = bridge_ptr->RelativeToGlobalBounds(ax_node_, offscreen, clip_bounds); if (offscreen_result != nullptr) { *offscreen_result = offscreen ? ui::AXOffscreenResult::kOffscreen : ui::AXOffscreenResult::kOnscreen; } return gfx::ToEnclosingRect(bounds); } std::weak_ptr FlutterPlatformNodeDelegate::GetOwnerBridge() const { return bridge_; } } // namespace flutter