OLD | NEW |
---|---|
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h" | 5 #include "chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "chrome/browser/extensions/api/automation_internal/automation_event_rou ter.h" | 9 #include "chrome/browser/extensions/api/automation_internal/automation_event_rou ter.h" |
10 #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h" | 10 #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h" |
11 #include "chrome/common/extensions/chrome_extension_messages.h" | 11 #include "chrome/common/extensions/chrome_extension_messages.h" |
12 #include "components/exo/wm_helper.h" | 12 #include "components/exo/wm_helper.h" |
13 #include "ui/accessibility/platform/ax_android_constants.h" | 13 #include "ui/accessibility/platform/ax_android_constants.h" |
14 #include "ui/aura/window.h" | 14 #include "ui/aura/window.h" |
15 #include "ui/views/focus/focus_manager.h" | |
16 #include "ui/views/view.h" | |
17 #include "ui/views/widget/widget.h" | |
15 | 18 |
16 namespace { | 19 namespace { |
17 | 20 |
21 // This class keeps focus on a |ShellSurface| without interfering with default | |
22 // focus management in |ShellSurface|. For example, touch causes the | |
23 // |ShellSurface| to lose focus to its ancestor containing View. | |
24 class FocusStealer : public views::View { | |
25 public: | |
26 explicit FocusStealer(int32_t id) : id_(id) { set_owned_by_client(); } | |
27 | |
28 void Steal() { | |
29 SetFocusBehavior(views::View::FocusBehavior::ALWAYS); | |
30 RequestFocus(); | |
31 parent()->NotifyAccessibilityEvent(ui::AX_EVENT_CHILDREN_CHANGED, false); | |
32 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, false); | |
33 } | |
34 | |
35 // views::View overrides. | |
36 void GetAccessibleNodeData(ui::AXNodeData* node_data) override { | |
37 node_data->AddIntAttribute(ui::AX_ATTR_CHILD_TREE_ID, id_); | |
38 node_data->role = ui::AX_ROLE_CLIENT; | |
39 } | |
40 | |
41 private: | |
42 int32_t id_; | |
Luis Héctor Chávez
2017/04/25 15:27:00
nit: const int32_t id_;
David Tseng
2017/04/25 22:48:02
Done.
| |
43 DISALLOW_COPY_AND_ASSIGN(FocusStealer); | |
44 }; | |
45 | |
18 ui::AXEvent ToAXEvent(arc::mojom::AccessibilityEventType arc_event_type) { | 46 ui::AXEvent ToAXEvent(arc::mojom::AccessibilityEventType arc_event_type) { |
19 switch (arc_event_type) { | 47 switch (arc_event_type) { |
20 case arc::mojom::AccessibilityEventType::VIEW_FOCUSED: | 48 case arc::mojom::AccessibilityEventType::VIEW_FOCUSED: |
21 case arc::mojom::AccessibilityEventType::VIEW_ACCESSIBILITY_FOCUSED: | 49 case arc::mojom::AccessibilityEventType::VIEW_ACCESSIBILITY_FOCUSED: |
22 return ui::AX_EVENT_FOCUS; | 50 return ui::AX_EVENT_FOCUS; |
23 case arc::mojom::AccessibilityEventType::VIEW_CLICKED: | 51 case arc::mojom::AccessibilityEventType::VIEW_CLICKED: |
24 case arc::mojom::AccessibilityEventType::VIEW_LONG_CLICKED: | 52 case arc::mojom::AccessibilityEventType::VIEW_LONG_CLICKED: |
25 return ui::AX_EVENT_CLICKED; | 53 return ui::AX_EVENT_CLICKED; |
26 case arc::mojom::AccessibilityEventType::VIEW_TEXT_CHANGED: | 54 case arc::mojom::AccessibilityEventType::VIEW_TEXT_CHANGED: |
27 return ui::AX_EVENT_TEXT_CHANGED; | 55 return ui::AX_EVENT_TEXT_CHANGED; |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
194 } | 222 } |
195 | 223 |
196 if (!GetBooleanProperty(node, AXBooleanProperty::ENABLED)) | 224 if (!GetBooleanProperty(node, AXBooleanProperty::ENABLED)) |
197 out_data->AddStateFlag(ui::AX_STATE_DISABLED); | 225 out_data->AddStateFlag(ui::AX_STATE_DISABLED); |
198 } | 226 } |
199 | 227 |
200 } // namespace | 228 } // namespace |
201 | 229 |
202 namespace arc { | 230 namespace arc { |
203 | 231 |
204 AXTreeSourceArc::AXTreeSourceArc(int32_t id) | 232 AXTreeSourceArc::AXTreeSourceArc(Delegate* delegate) |
205 : tree_id_(id), | 233 : current_tree_serializer_(new AXTreeArcSerializer(this)), |
206 current_tree_serializer_(new AXTreeArcSerializer(this)), | |
207 root_id_(-1), | 234 root_id_(-1), |
208 focused_node_id_(-1) {} | 235 focused_node_id_(-1), |
236 delegate_(delegate), | |
237 focus_stealer_(new FocusStealer(tree_id())) {} | |
209 | 238 |
210 AXTreeSourceArc::~AXTreeSourceArc() { | 239 AXTreeSourceArc::~AXTreeSourceArc() { |
211 Reset(); | 240 Reset(); |
212 } | 241 } |
213 | 242 |
214 void AXTreeSourceArc::NotifyAccessibilityEvent( | 243 void AXTreeSourceArc::NotifyAccessibilityEvent( |
215 mojom::AccessibilityEventData* event_data) { | 244 mojom::AccessibilityEventData* event_data) { |
216 tree_map_.clear(); | 245 tree_map_.clear(); |
217 parent_map_.clear(); | 246 parent_map_.clear(); |
218 root_id_ = -1; | 247 root_id_ = -1; |
(...skipping 16 matching lines...) Expand all Loading... | |
235 root_id_ = id; | 264 root_id_ = id; |
236 } | 265 } |
237 } | 266 } |
238 | 267 |
239 ExtensionMsg_AccessibilityEventParams params; | 268 ExtensionMsg_AccessibilityEventParams params; |
240 params.event_type = ToAXEvent(event_data->eventType); | 269 params.event_type = ToAXEvent(event_data->eventType); |
241 | 270 |
242 if (params.event_type == ui::AX_EVENT_FOCUS) | 271 if (params.event_type == ui::AX_EVENT_FOCUS) |
243 focused_node_id_ = event_data->sourceId; | 272 focused_node_id_ = event_data->sourceId; |
244 | 273 |
245 params.tree_id = tree_id_; | 274 params.tree_id = tree_id(); |
246 params.id = event_data->sourceId; | 275 params.id = event_data->sourceId; |
247 | 276 |
248 current_tree_serializer_->SerializeChanges(GetFromId(event_data->sourceId), | 277 current_tree_serializer_->SerializeChanges(GetFromId(event_data->sourceId), |
249 ¶ms.update); | 278 ¶ms.update); |
250 | 279 |
251 extensions::AutomationEventRouter* router = | 280 extensions::AutomationEventRouter* router = |
252 extensions::AutomationEventRouter::GetInstance(); | 281 extensions::AutomationEventRouter::GetInstance(); |
253 router->DispatchAccessibilityEvent(params); | 282 router->DispatchAccessibilityEvent(params); |
254 } | 283 } |
255 | 284 |
285 void AXTreeSourceArc::Focus(aura::Window* window) { | |
286 views::Widget* widget = views::Widget::GetWidgetForNativeView(window); | |
287 if (!widget || !widget->GetContentsView()) | |
288 return; | |
289 | |
290 views::View* view = widget->GetContentsView(); | |
291 if (!view->Contains(focus_stealer_.get())) | |
292 view->AddChildView(focus_stealer_.get()); | |
293 focus_stealer_->Steal(); | |
294 } | |
295 | |
256 bool AXTreeSourceArc::GetTreeData(ui::AXTreeData* data) const { | 296 bool AXTreeSourceArc::GetTreeData(ui::AXTreeData* data) const { |
257 data->tree_id = tree_id_; | 297 data->tree_id = tree_id(); |
258 if (focused_node_id_ >= 0) | 298 if (focused_node_id_ >= 0) |
259 data->focus_id = focused_node_id_; | 299 data->focus_id = focused_node_id_; |
260 return true; | 300 return true; |
261 } | 301 } |
262 | 302 |
263 mojom::AccessibilityNodeInfoData* AXTreeSourceArc::GetRoot() const { | 303 mojom::AccessibilityNodeInfoData* AXTreeSourceArc::GetRoot() const { |
264 mojom::AccessibilityNodeInfoData* root = GetFromId(root_id_); | 304 mojom::AccessibilityNodeInfoData* root = GetFromId(root_id_); |
265 return root; | 305 return root; |
266 } | 306 } |
267 | 307 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
353 // Integer properties. | 393 // Integer properties. |
354 int32_t val; | 394 int32_t val; |
355 if (GetIntProperty(node, AXIntProperty::TEXT_SELECTION_START, &val) && | 395 if (GetIntProperty(node, AXIntProperty::TEXT_SELECTION_START, &val) && |
356 val >= 0) | 396 val >= 0) |
357 out_data->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, val); | 397 out_data->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, val); |
358 | 398 |
359 if (GetIntProperty(node, AXIntProperty::TEXT_SELECTION_END, &val) && val >= 0) | 399 if (GetIntProperty(node, AXIntProperty::TEXT_SELECTION_END, &val) && val >= 0) |
360 out_data->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_END, val); | 400 out_data->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_END, val); |
361 } | 401 } |
362 | 402 |
403 void AXTreeSourceArc::PerformAction(const ui::AXActionData& data) { | |
404 delegate_->OnAction(data); | |
405 } | |
406 | |
363 void AXTreeSourceArc::Reset() { | 407 void AXTreeSourceArc::Reset() { |
364 tree_map_.clear(); | 408 tree_map_.clear(); |
365 parent_map_.clear(); | 409 parent_map_.clear(); |
366 current_tree_serializer_.reset(new AXTreeArcSerializer(this)); | 410 current_tree_serializer_.reset(new AXTreeArcSerializer(this)); |
367 root_id_ = -1; | 411 root_id_ = -1; |
368 focused_node_id_ = -1; | 412 focused_node_id_ = -1; |
369 extensions::AutomationEventRouter* router = | 413 extensions::AutomationEventRouter* router = |
370 extensions::AutomationEventRouter::GetInstance(); | 414 extensions::AutomationEventRouter::GetInstance(); |
371 router->DispatchTreeDestroyedEvent(tree_id_, nullptr); | 415 router->DispatchTreeDestroyedEvent(tree_id(), nullptr); |
372 } | 416 } |
373 | 417 |
374 } // namespace arc | 418 } // namespace arc |
OLD | NEW |