| Index: ui/views/accessibility/native_view_accessibility.cc
|
| diff --git a/ui/views/accessibility/native_view_accessibility.cc b/ui/views/accessibility/native_view_accessibility.cc
|
| index 6ca7676e6344d0b6339a33f10cea69cf5f19da91..d1e68009662c4537fea8136ad14db7164409d809 100644
|
| --- a/ui/views/accessibility/native_view_accessibility.cc
|
| +++ b/ui/views/accessibility/native_view_accessibility.cc
|
| @@ -4,7 +4,9 @@
|
|
|
| #include "ui/views/accessibility/native_view_accessibility.h"
|
|
|
| +#include "base/strings/utf_string_conversions.h"
|
| #include "ui/accessibility/ax_view_state.h"
|
| +#include "ui/views/controls/native/native_view_host.h"
|
| #include "ui/views/view.h"
|
| #include "ui/views/widget/widget.h"
|
|
|
| @@ -13,15 +15,12 @@ namespace views {
|
| #if !defined(OS_WIN)
|
| // static
|
| NativeViewAccessibility* NativeViewAccessibility::Create(View* view) {
|
| - DCHECK(view);
|
| - NativeViewAccessibility* instance = new NativeViewAccessibility();
|
| - instance->set_view(view);
|
| - return instance;
|
| + return new NativeViewAccessibility(view);
|
| }
|
| #endif
|
|
|
| -NativeViewAccessibility::NativeViewAccessibility()
|
| - : view_(NULL), ax_node_(ui::AXPlatformNode::Create(this)) {
|
| +NativeViewAccessibility::NativeViewAccessibility(View* view)
|
| + : view_(view), ax_node_(ui::AXPlatformNode::Create(this)) {
|
| }
|
|
|
| NativeViewAccessibility::~NativeViewAccessibility() {
|
| @@ -37,53 +36,197 @@ void NativeViewAccessibility::Destroy() {
|
| delete this;
|
| }
|
|
|
| -#if !defined(OS_WIN)
|
| -// static
|
| -void NativeViewAccessibility::RegisterWebView(View* web_view) {
|
| -}
|
| -
|
| -// static
|
| -void NativeViewAccessibility::UnregisterWebView(View* web_view) {
|
| +void NativeViewAccessibility::NotifyAccessibilityEvent(ui::AXEvent event_type) {
|
| + if (ax_node_)
|
| + ax_node_->NotifyAccessibilityEvent(event_type);
|
| }
|
| -#endif
|
|
|
| // ui::AXPlatformNodeDelegate
|
|
|
| -ui::AXNodeData* NativeViewAccessibility::GetData() {
|
| +const ui::AXNodeData* NativeViewAccessibility::GetData() {
|
| ui::AXViewState state;
|
| view_->GetAccessibleState(&state);
|
| + data_ = ui::AXNodeData();
|
| data_.role = state.role;
|
| + data_.state = state.state();
|
| data_.location = view_->GetBoundsInScreen();
|
| + data_.AddStringAttribute(ui::AX_ATTR_NAME, base::UTF16ToUTF8(state.name));
|
| + data_.AddStringAttribute(ui::AX_ATTR_VALUE, base::UTF16ToUTF8(state.value));
|
| + data_.AddStringAttribute(ui::AX_ATTR_ACTION,
|
| + base::UTF16ToUTF8(state.default_action));
|
| + data_.AddStringAttribute(ui::AX_ATTR_SHORTCUT,
|
| + base::UTF16ToUTF8(state.keyboard_shortcut));
|
| + data_.AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, state.selection_start);
|
| + data_.AddIntAttribute(ui::AX_ATTR_TEXT_SEL_END, state.selection_end);
|
| +
|
| + data_.state |= (1 << ui::AX_STATE_FOCUSABLE);
|
| +
|
| + if (!view_->enabled())
|
| + data_.state |= (1 << ui::AX_STATE_DISABLED);
|
| +
|
| + if (!view_->visible())
|
| + data_.state |= (1 << ui::AX_STATE_INVISIBLE);
|
| +
|
| + if (view_->HasFocus())
|
| + data_.state |= (1 << ui::AX_STATE_FOCUSED);
|
| +
|
| return &data_;
|
| }
|
|
|
| int NativeViewAccessibility::GetChildCount() {
|
| - return view_->child_count();
|
| + int child_count = view_->child_count();
|
| +
|
| + // If this is a root view, our widget might have child widgets. Include
|
| + // them, too.
|
| + if (view_->GetWidget() && view_->GetWidget()->GetRootView() == view_) {
|
| + std::vector<Widget*> child_widgets;
|
| + PopulateChildWidgetVector(&child_widgets);
|
| + child_count += child_widgets.size();
|
| + }
|
| +
|
| + return child_count;
|
| }
|
|
|
| gfx::NativeViewAccessible NativeViewAccessibility::ChildAtIndex(int index) {
|
| - if (index < 0 || index >= view_->child_count())
|
| - return NULL;
|
| - return view_->child_at(index)->GetNativeViewAccessible();
|
| + // If this is a root view, our widget might have child widgets. Include
|
| + std::vector<Widget*> child_widgets;
|
| + if (view_->GetWidget() && view_->GetWidget()->GetRootView() == view_)
|
| + PopulateChildWidgetVector(&child_widgets);
|
| + int child_widget_count = static_cast<int>(child_widgets.size());
|
| +
|
| + if (index < view_->child_count()) {
|
| + return view_->child_at(index)->GetNativeViewAccessible();
|
| + } else if (index < view_->child_count() + child_widget_count) {
|
| + Widget* child_widget = child_widgets[index - view_->child_count()];
|
| + return child_widget->GetRootView()->GetNativeViewAccessible();
|
| + }
|
| +
|
| + return NULL;
|
| }
|
|
|
| gfx::NativeViewAccessible NativeViewAccessibility::GetParent() {
|
| if (view_->parent())
|
| return view_->parent()->GetNativeViewAccessible();
|
|
|
| + // TODO: move this to NativeViewAccessibilityMac.
|
| #if defined(OS_MACOSX)
|
| - if (view_->GetWidget())
|
| + if (!view_->GetWidget())
|
| return view_->GetWidget()->GetNativeView();
|
| #endif
|
|
|
| return NULL;
|
| }
|
|
|
| +int NativeViewAccessibility::GetIndexInParent() {
|
| + if (!view_->parent())
|
| + return 0;
|
| + return view_->parent()->GetIndexOf(view_);
|
| +}
|
| +
|
| gfx::Vector2d NativeViewAccessibility::GetGlobalCoordinateOffset() {
|
| return gfx::Vector2d(0, 0); // location is already in screen coordinates.
|
| }
|
|
|
| -void NativeViewAccessibility::NotifyAccessibilityEvent(ui::AXEvent event_type) {
|
| +gfx::NativeViewAccessible NativeViewAccessibility::HitTestSync(int x, int y) {
|
| + if (!view_ || !view_->GetWidget())
|
| + return NULL;
|
| +
|
| + // If this is a root view, our widget might have child widgets.
|
| + // Search child widgets first, since they're on top in the z-order.
|
| + if (view_->GetWidget()->GetRootView() == view_) {
|
| + std::vector<Widget*> child_widgets;
|
| + PopulateChildWidgetVector(&child_widgets);
|
| + for (size_t i = 0; i < child_widgets.size(); ++i) {
|
| + Widget* child_widget = child_widgets[i];
|
| + View* child_root_view = child_widget->GetRootView();
|
| + gfx::Point point(x, y);
|
| + View::ConvertPointFromScreen(child_root_view, &point);
|
| + if (child_root_view->HitTestPoint(point))
|
| + return child_root_view->GetNativeViewAccessible();
|
| + }
|
| + }
|
| +
|
| + gfx::Point point(x, y);
|
| + View::ConvertPointFromScreen(view_, &point);
|
| +
|
| + // If the point is not inside this view, return NULL.
|
| + if (!view_->HitTestPoint(point))
|
| + return NULL;
|
| +
|
| + // Check if the point is within any of the immediate children of this
|
| + // view.
|
| + for (int i = view_->child_count() - 1; i >= 0; --i) {
|
| + View* child_view = view_->child_at(i);
|
| + if (!child_view->visible())
|
| + continue;
|
| +
|
| + gfx::Point point_in_child_coords(point);
|
| + view_->ConvertPointToTarget(view_, child_view, &point_in_child_coords);
|
| + if (child_view->HitTestPoint(point_in_child_coords))
|
| + return child_view->GetNativeViewAccessible();
|
| + }
|
| +
|
| + // If it's not inside any of our children, it's inside this view.
|
| + return GetNativeObject();
|
| +}
|
| +
|
| +gfx::NativeViewAccessible NativeViewAccessibility::GetFocus() {
|
| + FocusManager* focus_manager = view_->GetFocusManager();
|
| + View* focused_view = focus_manager ? focus_manager->GetFocusedView() : NULL;
|
| + return focused_view ? focused_view->GetNativeViewAccessible() : NULL;
|
| +}
|
| +
|
| +gfx::AcceleratedWidget
|
| +NativeViewAccessibility::GetTargetForNativeAccessibilityEvent() {
|
| + return gfx::kNullAcceleratedWidget;
|
| +}
|
| +
|
| +void NativeViewAccessibility::DoDefaultAction() {
|
| + gfx::Point center = view_->GetLocalBounds().CenterPoint();
|
| + view_->OnMousePressed(ui::MouseEvent(ui::ET_MOUSE_PRESSED,
|
| + center,
|
| + center,
|
| + ui::EF_LEFT_MOUSE_BUTTON,
|
| + ui::EF_LEFT_MOUSE_BUTTON));
|
| + view_->OnMouseReleased(ui::MouseEvent(ui::ET_MOUSE_RELEASED,
|
| + center,
|
| + center,
|
| + ui::EF_LEFT_MOUSE_BUTTON,
|
| + ui::EF_LEFT_MOUSE_BUTTON));
|
| +}
|
| +
|
| +bool NativeViewAccessibility::SetStringValue(const base::string16& new_value) {
|
| + // Return an error if the view can't set the value.
|
| + ui::AXViewState state;
|
| + view_->GetAccessibleState(&state);
|
| + if (state.set_value_callback.is_null())
|
| + return false;
|
| +
|
| + state.set_value_callback.Run(new_value);
|
| + return true;
|
| +}
|
| +
|
| +void NativeViewAccessibility::PopulateChildWidgetVector(
|
| + std::vector<Widget*>* result_child_widgets) {
|
| + const Widget* widget = view_->GetWidget();
|
| + if (!widget)
|
| + return;
|
| +
|
| + std::set<Widget*> child_widgets;
|
| + Widget::GetAllOwnedWidgets(widget->GetNativeView(), &child_widgets);
|
| + for (std::set<Widget*>::const_iterator iter = child_widgets.begin();
|
| + iter != child_widgets.end(); ++iter) {
|
| + Widget* child_widget = *iter;
|
| + DCHECK_NE(widget, child_widget);
|
| +
|
| + if (!child_widget->IsVisible())
|
| + continue;
|
| +
|
| + if (widget->GetNativeWindowProperty(kWidgetNativeViewHostKey))
|
| + continue;
|
| +
|
| + result_child_widgets->push_back(child_widget);
|
| + }
|
| }
|
|
|
| } // namespace views
|
|
|