blob: 8f636909a243de716657d80aed9047f5e2d4bd99 [file] [log] [blame]
// 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 "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<OwnerBridge> bridge,
ui::AXNode* node) {
bridge_ = 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<int>(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::OwnerBridge>
FlutterPlatformNodeDelegate::GetOwnerBridge() const {
return bridge_;
}
} // namespace flutter