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 |