OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/views/accessibility/native_view_accessibility.h" | 5 #include "ui/views/accessibility/native_view_accessibility.h" |
6 | 6 |
7 #include "base/strings/utf_string_conversions.h" | 7 #include "base/strings/utf_string_conversions.h" |
8 #include "build/build_config.h" | 8 #include "build/build_config.h" |
9 #include "ui/accessibility/ax_view_state.h" | 9 #include "ui/accessibility/ax_view_state.h" |
10 #include "ui/events/event_utils.h" | 10 #include "ui/events/event_utils.h" |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 if (!view_->enabled()) | 82 if (!view_->enabled()) |
83 data_.state |= (1 << ui::AX_STATE_DISABLED); | 83 data_.state |= (1 << ui::AX_STATE_DISABLED); |
84 | 84 |
85 if (!view_->visible()) | 85 if (!view_->visible()) |
86 data_.state |= (1 << ui::AX_STATE_INVISIBLE); | 86 data_.state |= (1 << ui::AX_STATE_INVISIBLE); |
87 | 87 |
88 return data_; | 88 return data_; |
89 } | 89 } |
90 | 90 |
91 int NativeViewAccessibility::GetChildCount() { | 91 int NativeViewAccessibility::GetChildCount() { |
92 int child_count = view_->child_count(); | 92 int child_count = 0; |
| 93 for (int i = 0; i < view_->child_count(); ++i) { |
| 94 View* child = view_->child_at(i); |
| 95 if (child->GetNativeViewAccessibility()->IsIgnored()) { |
| 96 // If not visible to accessibility clients, then use the children instead. |
| 97 child_count += child->GetNativeViewAccessibility()->GetChildCount(); |
| 98 } else { |
| 99 ++child_count; |
| 100 } |
| 101 } |
93 | 102 |
94 std::vector<Widget*> child_widgets; | 103 std::vector<Widget*> child_widgets; |
95 PopulateChildWidgetVector(&child_widgets); | 104 PopulateChildWidgetVector(&child_widgets); |
96 child_count += child_widgets.size(); | 105 child_count += child_widgets.size(); |
97 | 106 |
98 return child_count; | 107 return child_count; |
99 } | 108 } |
100 | 109 |
101 gfx::NativeViewAccessible NativeViewAccessibility::ChildAtIndex(int index) { | 110 gfx::NativeViewAccessible NativeViewAccessibility::ChildAtIndex(int index) { |
102 // If this is a root view, our widget might have child widgets. Include | 111 if (IsLeafElement()) |
| 112 return nullptr; |
| 113 |
| 114 // Include the child widgets that may be present if this is a root view. |
103 std::vector<Widget*> child_widgets; | 115 std::vector<Widget*> child_widgets; |
104 PopulateChildWidgetVector(&child_widgets); | 116 PopulateChildWidgetVector(&child_widgets); |
105 int child_widget_count = static_cast<int>(child_widgets.size()); | 117 int child_widget_count = static_cast<int>(child_widgets.size()); |
106 | 118 |
107 if (index < view_->child_count()) { | 119 int ax_child_count = GetChildCount(); |
108 return view_->child_at(index)->GetNativeViewAccessible(); | 120 if (index < ax_child_count) { |
109 } else if (index < view_->child_count() + child_widget_count) { | 121 int curr_child_count = 0; |
| 122 for (int i = 0; i < view_->child_count(); ++i) { |
| 123 View* child = view_->child_at(i); |
| 124 bool ignored = child->GetNativeViewAccessibility()->IsIgnored(); |
| 125 int pending_children = |
| 126 ignored ? child->GetNativeViewAccessibility()->GetChildCount() : 1; |
| 127 if (index < curr_child_count + pending_children) { |
| 128 if (ignored) { |
| 129 return child->GetNativeViewAccessibility()->ChildAtIndex( |
| 130 index - curr_child_count); |
| 131 } |
| 132 return child->GetNativeViewAccessible(); |
| 133 } |
| 134 curr_child_count += pending_children; |
| 135 } |
| 136 } else if (index < ax_child_count + child_widget_count) { |
110 Widget* child_widget = child_widgets[index - view_->child_count()]; | 137 Widget* child_widget = child_widgets[index - view_->child_count()]; |
111 return child_widget->GetRootView()->GetNativeViewAccessible(); | 138 return child_widget->GetRootView()->GetNativeViewAccessible(); |
112 } | 139 } |
113 | 140 |
114 return nullptr; | 141 return nullptr; |
115 } | 142 } |
116 | 143 |
117 gfx::NativeWindow NativeViewAccessibility::GetTopLevelWidget() { | 144 gfx::NativeWindow NativeViewAccessibility::GetTopLevelWidget() { |
118 if (view_->GetWidget()) | 145 if (view_->GetWidget()) |
119 return view_->GetWidget()->GetTopLevelWidget()->GetNativeWindow(); | 146 return view_->GetWidget()->GetTopLevelWidget()->GetNativeWindow(); |
120 return nullptr; | 147 return nullptr; |
121 } | 148 } |
122 | 149 |
123 gfx::NativeViewAccessible NativeViewAccessibility::GetParent() { | 150 gfx::NativeViewAccessible NativeViewAccessibility::GetParent() { |
124 if (view_->parent()) | 151 View* parent_view = view_->parent(); |
125 return view_->parent()->GetNativeViewAccessible(); | 152 if (parent_view) { |
| 153 if (parent_view->GetNativeViewAccessibility()->IsIgnored()) |
| 154 return parent_view->GetNativeViewAccessibility()->GetParent(); |
| 155 else |
| 156 return parent_view->GetNativeViewAccessible(); |
| 157 } |
126 | 158 |
127 // TODO: move this to NativeViewAccessibilityMac. | 159 // TODO: move this to NativeViewAccessibilityMac. |
128 #if defined(OS_MACOSX) | 160 #if defined(OS_MACOSX) |
129 if (view_->GetWidget()) | 161 if (view_->GetWidget()) |
130 return view_->GetWidget()->GetNativeView(); | 162 return view_->GetWidget()->GetNativeView(); |
131 #endif | 163 #endif |
132 | 164 |
133 if (parent_widget_) | 165 if (parent_widget_) |
134 return parent_widget_->GetRootView()->GetNativeViewAccessible(); | 166 return parent_widget_->GetRootView()->GetNativeViewAccessible(); |
135 | 167 |
(...skipping 12 matching lines...) Expand all Loading... |
148 std::vector<Widget*> child_widgets; | 180 std::vector<Widget*> child_widgets; |
149 PopulateChildWidgetVector(&child_widgets); | 181 PopulateChildWidgetVector(&child_widgets); |
150 for (Widget* child_widget : child_widgets) { | 182 for (Widget* child_widget : child_widgets) { |
151 View* child_root_view = child_widget->GetRootView(); | 183 View* child_root_view = child_widget->GetRootView(); |
152 gfx::Point point(x, y); | 184 gfx::Point point(x, y); |
153 View::ConvertPointFromScreen(child_root_view, &point); | 185 View::ConvertPointFromScreen(child_root_view, &point); |
154 if (child_root_view->HitTestPoint(point)) | 186 if (child_root_view->HitTestPoint(point)) |
155 return child_root_view->GetNativeViewAccessible(); | 187 return child_root_view->GetNativeViewAccessible(); |
156 } | 188 } |
157 | 189 |
| 190 if (IsLeafElement()) { |
| 191 if (IsIgnored()) |
| 192 return GetParent(); |
| 193 return GetNativeObject(); |
| 194 } |
| 195 |
158 gfx::Point point(x, y); | 196 gfx::Point point(x, y); |
159 View::ConvertPointFromScreen(view_, &point); | 197 View::ConvertPointFromScreen(view_, &point); |
160 if (!view_->HitTestPoint(point)) | 198 if (!view_->HitTestPoint(point)) |
161 return nullptr; | 199 return nullptr; |
162 | 200 |
163 // Check if the point is within any of the immediate children of this | 201 // Check if the point is within any of the immediate children of this view. We |
164 // view. We don't have to search further because AXPlatformNode will | 202 // don't have to search further because AXPlatformNodeWin will do a recursive |
165 // do a recursive hit test if we return anything other than |this| or NULL. | 203 // hit test if we return anything other than |GetNativeObject()| or nullptr. |
166 for (int i = view_->child_count() - 1; i >= 0; --i) { | 204 for (int i = view_->child_count() - 1; i >= 0; --i) { |
167 View* child_view = view_->child_at(i); | 205 View* child_view = view_->child_at(i); |
168 if (!child_view->visible()) | 206 if (!child_view->visible()) |
169 continue; | 207 continue; |
170 | 208 |
171 gfx::Point point_in_child_coords(point); | 209 gfx::Point point_in_child_coords(point); |
172 view_->ConvertPointToTarget(view_, child_view, &point_in_child_coords); | 210 view_->ConvertPointToTarget(view_, child_view, &point_in_child_coords); |
173 if (child_view->HitTestPoint(point_in_child_coords)) | 211 if (child_view->HitTestPoint(point_in_child_coords)) |
174 return child_view->GetNativeViewAccessible(); | 212 return child_view->GetNativeViewAccessible(); |
175 } | 213 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 } | 269 } |
232 } | 270 } |
233 | 271 |
234 void NativeViewAccessibility::SetParentWidget(Widget* parent_widget) { | 272 void NativeViewAccessibility::SetParentWidget(Widget* parent_widget) { |
235 if (parent_widget_) | 273 if (parent_widget_) |
236 parent_widget_->RemoveObserver(this); | 274 parent_widget_->RemoveObserver(this); |
237 parent_widget_ = parent_widget; | 275 parent_widget_ = parent_widget; |
238 parent_widget_->AddObserver(this); | 276 parent_widget_->AddObserver(this); |
239 } | 277 } |
240 | 278 |
| 279 bool NativeViewAccessibility::IsLeafElement() { |
| 280 if (GetChildCount() != 0) |
| 281 return false; |
| 282 return true; |
| 283 } |
| 284 |
| 285 bool NativeViewAccessibility::IsIgnored() { |
| 286 if (view_->focus_behavior() == ClientView::FocusBehavior::NEVER) |
| 287 return true; |
| 288 return false; |
| 289 } |
| 290 |
241 void NativeViewAccessibility::PopulateChildWidgetVector( | 291 void NativeViewAccessibility::PopulateChildWidgetVector( |
242 std::vector<Widget*>* result_child_widgets) { | 292 std::vector<Widget*>* result_child_widgets) { |
243 // Only attach child widgets to the root view. | 293 // Only attach child widgets to the root view. |
244 Widget* widget = view_->GetWidget(); | 294 Widget* widget = view_->GetWidget(); |
245 if (!widget || widget->GetRootView() != view_) | 295 if (!widget || widget->GetRootView() != view_) |
246 return; | 296 return; |
247 | 297 |
248 std::set<Widget*> child_widgets; | 298 std::set<Widget*> child_widgets; |
249 Widget::GetAllOwnedWidgets(widget->GetNativeView(), &child_widgets); | 299 Widget::GetAllOwnedWidgets(widget->GetNativeView(), &child_widgets); |
250 for (auto iter = child_widgets.begin(); iter != child_widgets.end(); ++iter) { | 300 for (auto iter = child_widgets.begin(); iter != child_widgets.end(); ++iter) { |
(...skipping 16 matching lines...) Expand all Loading... |
267 child_widget_platform_node->GetDelegate()); | 317 child_widget_platform_node->GetDelegate()); |
268 if (child_widget_view_accessibility->parent_widget() != widget) | 318 if (child_widget_view_accessibility->parent_widget() != widget) |
269 child_widget_view_accessibility->SetParentWidget(widget); | 319 child_widget_view_accessibility->SetParentWidget(widget); |
270 } | 320 } |
271 | 321 |
272 result_child_widgets->push_back(child_widget); | 322 result_child_widgets->push_back(child_widget); |
273 } | 323 } |
274 } | 324 } |
275 | 325 |
276 } // namespace views | 326 } // namespace views |
OLD | NEW |