Make castv2 performance test work.
[chromium-blink-merge.git] / ui / views / accessibility / native_view_accessibility.cc
bloba11f773d62a67e816bda3fb3a240bd1bed693905
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/views/accessibility/native_view_accessibility.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "ui/accessibility/ax_view_state.h"
9 #include "ui/events/event_utils.h"
10 #include "ui/views/controls/native/native_view_host.h"
11 #include "ui/views/view.h"
12 #include "ui/views/widget/widget.h"
14 namespace views {
16 #if !defined(OS_WIN) && !(defined(OS_LINUX) && !defined(OS_CHROMEOS))
17 // static
18 NativeViewAccessibility* NativeViewAccessibility::Create(View* view) {
19 return new NativeViewAccessibility(view);
21 #endif
23 NativeViewAccessibility::NativeViewAccessibility(View* view)
24 : view_(view),
25 parent_widget_(nullptr),
26 ax_node_(nullptr) {
27 ax_node_ = ui::AXPlatformNode::Create(this);
30 NativeViewAccessibility::~NativeViewAccessibility() {
31 if (ax_node_)
32 ax_node_->Destroy();
33 if (parent_widget_)
34 parent_widget_->RemoveObserver(this);
37 gfx::NativeViewAccessible NativeViewAccessibility::GetNativeObject() {
38 return ax_node_ ? ax_node_->GetNativeViewAccessible() : nullptr;
41 void NativeViewAccessibility::Destroy() {
42 delete this;
45 void NativeViewAccessibility::NotifyAccessibilityEvent(ui::AXEvent event_type) {
46 if (ax_node_)
47 ax_node_->NotifyAccessibilityEvent(event_type);
50 // ui::AXPlatformNodeDelegate
52 const ui::AXNodeData& NativeViewAccessibility::GetData() {
53 ui::AXViewState state;
54 view_->GetAccessibleState(&state);
55 data_ = ui::AXNodeData();
56 data_.role = state.role;
57 data_.state = state.state();
58 data_.location = view_->GetBoundsInScreen();
59 data_.AddStringAttribute(ui::AX_ATTR_NAME, base::UTF16ToUTF8(state.name));
60 data_.AddStringAttribute(ui::AX_ATTR_VALUE, base::UTF16ToUTF8(state.value));
61 data_.AddStringAttribute(ui::AX_ATTR_ACTION,
62 base::UTF16ToUTF8(state.default_action));
63 data_.AddStringAttribute(ui::AX_ATTR_SHORTCUT,
64 base::UTF16ToUTF8(state.keyboard_shortcut));
65 data_.AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, state.selection_start);
66 data_.AddIntAttribute(ui::AX_ATTR_TEXT_SEL_END, state.selection_end);
68 data_.state |= (1 << ui::AX_STATE_FOCUSABLE);
70 if (!view_->enabled())
71 data_.state |= (1 << ui::AX_STATE_DISABLED);
73 if (!view_->visible())
74 data_.state |= (1 << ui::AX_STATE_INVISIBLE);
76 if (view_->HasFocus())
77 data_.state |= (1 << ui::AX_STATE_FOCUSED);
79 return data_;
82 int NativeViewAccessibility::GetChildCount() {
83 int child_count = view_->child_count();
85 std::vector<Widget*> child_widgets;
86 PopulateChildWidgetVector(&child_widgets);
87 child_count += child_widgets.size();
89 return child_count;
92 gfx::NativeViewAccessible NativeViewAccessibility::ChildAtIndex(int index) {
93 // If this is a root view, our widget might have child widgets. Include
94 std::vector<Widget*> child_widgets;
95 PopulateChildWidgetVector(&child_widgets);
96 int child_widget_count = static_cast<int>(child_widgets.size());
98 if (index < view_->child_count()) {
99 return view_->child_at(index)->GetNativeViewAccessible();
100 } else if (index < view_->child_count() + child_widget_count) {
101 Widget* child_widget = child_widgets[index - view_->child_count()];
102 return child_widget->GetRootView()->GetNativeViewAccessible();
105 return nullptr;
108 gfx::NativeViewAccessible NativeViewAccessibility::GetParent() {
109 if (view_->parent())
110 return view_->parent()->GetNativeViewAccessible();
112 // TODO: move this to NativeViewAccessibilityMac.
113 #if defined(OS_MACOSX)
114 if (view_->GetWidget())
115 return view_->GetWidget()->GetNativeView();
116 #endif
118 if (parent_widget_)
119 return parent_widget_->GetRootView()->GetNativeViewAccessible();
121 return nullptr;
124 gfx::Vector2d NativeViewAccessibility::GetGlobalCoordinateOffset() {
125 return gfx::Vector2d(0, 0); // location is already in screen coordinates.
128 gfx::NativeViewAccessible NativeViewAccessibility::HitTestSync(int x, int y) {
129 if (!view_ || !view_->GetWidget())
130 return nullptr;
132 // Search child widgets first, since they're on top in the z-order.
133 std::vector<Widget*> child_widgets;
134 PopulateChildWidgetVector(&child_widgets);
135 for (Widget* child_widget : child_widgets) {
136 View* child_root_view = child_widget->GetRootView();
137 gfx::Point point(x, y);
138 View::ConvertPointFromScreen(child_root_view, &point);
139 if (child_root_view->HitTestPoint(point))
140 return child_root_view->GetNativeViewAccessible();
143 gfx::Point point(x, y);
144 View::ConvertPointFromScreen(view_, &point);
145 if (!view_->HitTestPoint(point))
146 return nullptr;
148 // Check if the point is within any of the immediate children of this
149 // view. We don't have to search further because AXPlatformNode will
150 // do a recursive hit test if we return anything other than |this| or NULL.
151 for (int i = view_->child_count() - 1; i >= 0; --i) {
152 View* child_view = view_->child_at(i);
153 if (!child_view->visible())
154 continue;
156 gfx::Point point_in_child_coords(point);
157 view_->ConvertPointToTarget(view_, child_view, &point_in_child_coords);
158 if (child_view->HitTestPoint(point_in_child_coords))
159 return child_view->GetNativeViewAccessible();
162 // If it's not inside any of our children, it's inside this view.
163 return GetNativeObject();
166 gfx::NativeViewAccessible NativeViewAccessibility::GetFocus() {
167 FocusManager* focus_manager = view_->GetFocusManager();
168 View* focused_view =
169 focus_manager ? focus_manager->GetFocusedView() : nullptr;
170 return focused_view ? focused_view->GetNativeViewAccessible() : nullptr;
173 gfx::AcceleratedWidget
174 NativeViewAccessibility::GetTargetForNativeAccessibilityEvent() {
175 return gfx::kNullAcceleratedWidget;
178 void NativeViewAccessibility::DoDefaultAction() {
179 gfx::Point center = view_->GetLocalBounds().CenterPoint();
180 view_->OnMousePressed(ui::MouseEvent(ui::ET_MOUSE_PRESSED,
181 center,
182 center,
183 ui::EventTimeForNow(),
184 ui::EF_LEFT_MOUSE_BUTTON,
185 ui::EF_LEFT_MOUSE_BUTTON));
186 view_->OnMouseReleased(ui::MouseEvent(ui::ET_MOUSE_RELEASED,
187 center,
188 center,
189 ui::EventTimeForNow(),
190 ui::EF_LEFT_MOUSE_BUTTON,
191 ui::EF_LEFT_MOUSE_BUTTON));
194 bool NativeViewAccessibility::SetStringValue(const base::string16& new_value) {
195 // Return an error if the view can't set the value.
196 ui::AXViewState state;
197 view_->GetAccessibleState(&state);
198 if (state.set_value_callback.is_null())
199 return false;
201 state.set_value_callback.Run(new_value);
202 return true;
205 void NativeViewAccessibility::OnWidgetDestroying(Widget* widget) {
206 if (parent_widget_ == widget)
207 parent_widget_ = nullptr;
210 void NativeViewAccessibility::SetParentWidget(Widget* parent_widget) {
211 if (parent_widget_)
212 parent_widget_->RemoveObserver(this);
213 parent_widget_ = parent_widget;
214 parent_widget_->AddObserver(this);
217 void NativeViewAccessibility::PopulateChildWidgetVector(
218 std::vector<Widget*>* result_child_widgets) {
219 // Only attach child widgets to the root view.
220 Widget* widget = view_->GetWidget();
221 if (!widget || widget->GetRootView() != view_)
222 return;
224 std::set<Widget*> child_widgets;
225 Widget::GetAllOwnedWidgets(widget->GetNativeView(), &child_widgets);
226 for (auto iter = child_widgets.begin(); iter != child_widgets.end(); ++iter) {
227 Widget* child_widget = *iter;
228 DCHECK_NE(widget, child_widget);
230 if (!child_widget->IsVisible())
231 continue;
233 if (widget->GetNativeWindowProperty(kWidgetNativeViewHostKey))
234 continue;
236 gfx::NativeViewAccessible child_widget_accessible =
237 child_widget->GetRootView()->GetNativeViewAccessible();
238 ui::AXPlatformNode* child_widget_platform_node =
239 ui::AXPlatformNode::FromNativeViewAccessible(child_widget_accessible);
240 if (child_widget_platform_node) {
241 NativeViewAccessibility* child_widget_view_accessibility =
242 static_cast<NativeViewAccessibility*>(
243 child_widget_platform_node->GetDelegate());
244 if (child_widget_view_accessibility->parent_widget() != widget)
245 child_widget_view_accessibility->SetParentWidget(widget);
248 result_child_widgets->push_back(child_widget);
252 } // namespace views