| 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 |
| 18 ui::AXEvent ToAXEvent(arc::mojom::AccessibilityEventType arc_event_type) { | 21 ui::AXEvent ToAXEvent(arc::mojom::AccessibilityEventType arc_event_type) { |
| 19 switch (arc_event_type) { | 22 switch (arc_event_type) { |
| 20 case arc::mojom::AccessibilityEventType::VIEW_FOCUSED: | 23 case arc::mojom::AccessibilityEventType::VIEW_FOCUSED: |
| 21 case arc::mojom::AccessibilityEventType::VIEW_ACCESSIBILITY_FOCUSED: | 24 case arc::mojom::AccessibilityEventType::VIEW_ACCESSIBILITY_FOCUSED: |
| 22 return ui::AX_EVENT_FOCUS; | 25 return ui::AX_EVENT_FOCUS; |
| 23 case arc::mojom::AccessibilityEventType::VIEW_CLICKED: | 26 case arc::mojom::AccessibilityEventType::VIEW_CLICKED: |
| 24 case arc::mojom::AccessibilityEventType::VIEW_LONG_CLICKED: | 27 case arc::mojom::AccessibilityEventType::VIEW_LONG_CLICKED: |
| (...skipping 25 matching lines...) Expand all Loading... |
| 50 case arc::mojom::AccessibilityEventType::VIEW_CONTEXT_CLICKED: | 53 case arc::mojom::AccessibilityEventType::VIEW_CONTEXT_CLICKED: |
| 51 case arc::mojom::AccessibilityEventType::ASSIST_READING_CONTEXT: | 54 case arc::mojom::AccessibilityEventType::ASSIST_READING_CONTEXT: |
| 52 return ui::AX_EVENT_CHILDREN_CHANGED; | 55 return ui::AX_EVENT_CHILDREN_CHANGED; |
| 53 default: | 56 default: |
| 54 return ui::AX_EVENT_CHILDREN_CHANGED; | 57 return ui::AX_EVENT_CHILDREN_CHANGED; |
| 55 } | 58 } |
| 56 return ui::AX_EVENT_CHILDREN_CHANGED; | 59 return ui::AX_EVENT_CHILDREN_CHANGED; |
| 57 } | 60 } |
| 58 | 61 |
| 59 const gfx::Rect GetBounds(arc::mojom::AccessibilityNodeInfoData* node) { | 62 const gfx::Rect GetBounds(arc::mojom::AccessibilityNodeInfoData* node) { |
| 60 exo::WMHelper* wmHelper = exo::WMHelper::GetInstance(); | 63 exo::WMHelper* wm_helper = exo::WMHelper::GetInstance(); |
| 61 aura::Window* focused_window = wmHelper->GetFocusedWindow(); | 64 if (!wm_helper) |
| 65 return gfx::Rect(); |
| 66 |
| 67 aura::Window* focused_window = wm_helper->GetFocusedWindow(); |
| 62 gfx::Rect bounds_in_screen = node->boundsInScreen; | 68 gfx::Rect bounds_in_screen = node->boundsInScreen; |
| 63 if (focused_window) { | 69 if (focused_window) { |
| 64 aura::Window* toplevel_window = focused_window->GetToplevelWindow(); | 70 aura::Window* toplevel_window = focused_window->GetToplevelWindow(); |
| 65 return gfx::ScaleToEnclosingRect( | 71 return gfx::ScaleToEnclosingRect( |
| 66 bounds_in_screen, | 72 bounds_in_screen, |
| 67 1.0f / toplevel_window->layer()->device_scale_factor()); | 73 1.0f / toplevel_window->layer()->device_scale_factor()); |
| 68 } | 74 } |
| 69 return bounds_in_screen; | 75 return bounds_in_screen; |
| 70 } | 76 } |
| 71 | 77 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 } | 200 } |
| 195 | 201 |
| 196 if (!GetBooleanProperty(node, AXBooleanProperty::ENABLED)) | 202 if (!GetBooleanProperty(node, AXBooleanProperty::ENABLED)) |
| 197 out_data->AddStateFlag(ui::AX_STATE_DISABLED); | 203 out_data->AddStateFlag(ui::AX_STATE_DISABLED); |
| 198 } | 204 } |
| 199 | 205 |
| 200 } // namespace | 206 } // namespace |
| 201 | 207 |
| 202 namespace arc { | 208 namespace arc { |
| 203 | 209 |
| 204 AXTreeSourceArc::AXTreeSourceArc(int32_t id) | 210 // This class keeps focus on a |ShellSurface| without interfering with default |
| 205 : tree_id_(id), | 211 // focus management in |ShellSurface|. For example, touch causes the |
| 206 current_tree_serializer_(new AXTreeArcSerializer(this)), | 212 // |ShellSurface| to lose focus to its ancestor containing View. |
| 213 class AXTreeSourceArc::FocusStealer : public views::View { |
| 214 public: |
| 215 explicit FocusStealer(int32_t id) : id_(id) { set_owned_by_client(); } |
| 216 |
| 217 void Steal() { |
| 218 SetFocusBehavior(views::View::FocusBehavior::ALWAYS); |
| 219 RequestFocus(); |
| 220 } |
| 221 |
| 222 // views::View overrides. |
| 223 void GetAccessibleNodeData(ui::AXNodeData* node_data) override { |
| 224 node_data->AddIntAttribute(ui::AX_ATTR_CHILD_TREE_ID, id_); |
| 225 node_data->role = ui::AX_ROLE_CLIENT; |
| 226 } |
| 227 |
| 228 private: |
| 229 const int32_t id_; |
| 230 DISALLOW_COPY_AND_ASSIGN(FocusStealer); |
| 231 }; |
| 232 |
| 233 AXTreeSourceArc::AXTreeSourceArc(Delegate* delegate) |
| 234 : current_tree_serializer_(new AXTreeArcSerializer(this)), |
| 207 root_id_(-1), | 235 root_id_(-1), |
| 208 focused_node_id_(-1) {} | 236 focused_node_id_(-1), |
| 237 delegate_(delegate), |
| 238 focus_stealer_(new FocusStealer(tree_id())) {} |
| 209 | 239 |
| 210 AXTreeSourceArc::~AXTreeSourceArc() { | 240 AXTreeSourceArc::~AXTreeSourceArc() { |
| 211 Reset(); | 241 Reset(); |
| 212 } | 242 } |
| 213 | 243 |
| 214 void AXTreeSourceArc::NotifyAccessibilityEvent( | 244 void AXTreeSourceArc::NotifyAccessibilityEvent( |
| 215 mojom::AccessibilityEventData* event_data) { | 245 mojom::AccessibilityEventData* event_data) { |
| 216 tree_map_.clear(); | 246 tree_map_.clear(); |
| 217 parent_map_.clear(); | 247 parent_map_.clear(); |
| 218 root_id_ = -1; | 248 root_id_ = -1; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 235 root_id_ = id; | 265 root_id_ = id; |
| 236 } | 266 } |
| 237 } | 267 } |
| 238 | 268 |
| 239 ExtensionMsg_AccessibilityEventParams params; | 269 ExtensionMsg_AccessibilityEventParams params; |
| 240 params.event_type = ToAXEvent(event_data->eventType); | 270 params.event_type = ToAXEvent(event_data->eventType); |
| 241 | 271 |
| 242 if (params.event_type == ui::AX_EVENT_FOCUS) | 272 if (params.event_type == ui::AX_EVENT_FOCUS) |
| 243 focused_node_id_ = event_data->sourceId; | 273 focused_node_id_ = event_data->sourceId; |
| 244 | 274 |
| 245 params.tree_id = tree_id_; | 275 params.tree_id = tree_id(); |
| 246 params.id = event_data->sourceId; | 276 params.id = event_data->sourceId; |
| 247 | 277 |
| 248 current_tree_serializer_->SerializeChanges(GetFromId(event_data->sourceId), | 278 current_tree_serializer_->SerializeChanges(GetFromId(event_data->sourceId), |
| 249 ¶ms.update); | 279 ¶ms.update); |
| 250 | 280 |
| 251 extensions::AutomationEventRouter* router = | 281 extensions::AutomationEventRouter* router = |
| 252 extensions::AutomationEventRouter::GetInstance(); | 282 extensions::AutomationEventRouter::GetInstance(); |
| 253 router->DispatchAccessibilityEvent(params); | 283 router->DispatchAccessibilityEvent(params); |
| 254 } | 284 } |
| 255 | 285 |
| 286 void AXTreeSourceArc::Focus(aura::Window* window) { |
| 287 views::Widget* widget = views::Widget::GetWidgetForNativeView(window); |
| 288 if (!widget || !widget->GetContentsView()) |
| 289 return; |
| 290 |
| 291 views::View* view = widget->GetContentsView(); |
| 292 if (!view->Contains(focus_stealer_.get())) |
| 293 view->AddChildView(focus_stealer_.get()); |
| 294 focus_stealer_->Steal(); |
| 295 } |
| 296 |
| 256 bool AXTreeSourceArc::GetTreeData(ui::AXTreeData* data) const { | 297 bool AXTreeSourceArc::GetTreeData(ui::AXTreeData* data) const { |
| 257 data->tree_id = tree_id_; | 298 data->tree_id = tree_id(); |
| 258 if (focused_node_id_ >= 0) | 299 if (focused_node_id_ >= 0) |
| 259 data->focus_id = focused_node_id_; | 300 data->focus_id = focused_node_id_; |
| 260 return true; | 301 return true; |
| 261 } | 302 } |
| 262 | 303 |
| 263 mojom::AccessibilityNodeInfoData* AXTreeSourceArc::GetRoot() const { | 304 mojom::AccessibilityNodeInfoData* AXTreeSourceArc::GetRoot() const { |
| 264 mojom::AccessibilityNodeInfoData* root = GetFromId(root_id_); | 305 mojom::AccessibilityNodeInfoData* root = GetFromId(root_id_); |
| 265 return root; | 306 return root; |
| 266 } | 307 } |
| 267 | 308 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 // Integer properties. | 394 // Integer properties. |
| 354 int32_t val; | 395 int32_t val; |
| 355 if (GetIntProperty(node, AXIntProperty::TEXT_SELECTION_START, &val) && | 396 if (GetIntProperty(node, AXIntProperty::TEXT_SELECTION_START, &val) && |
| 356 val >= 0) | 397 val >= 0) |
| 357 out_data->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, val); | 398 out_data->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, val); |
| 358 | 399 |
| 359 if (GetIntProperty(node, AXIntProperty::TEXT_SELECTION_END, &val) && val >= 0) | 400 if (GetIntProperty(node, AXIntProperty::TEXT_SELECTION_END, &val) && val >= 0) |
| 360 out_data->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_END, val); | 401 out_data->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_END, val); |
| 361 } | 402 } |
| 362 | 403 |
| 404 void AXTreeSourceArc::PerformAction(const ui::AXActionData& data) { |
| 405 delegate_->OnAction(data); |
| 406 } |
| 407 |
| 363 void AXTreeSourceArc::Reset() { | 408 void AXTreeSourceArc::Reset() { |
| 364 tree_map_.clear(); | 409 tree_map_.clear(); |
| 365 parent_map_.clear(); | 410 parent_map_.clear(); |
| 366 current_tree_serializer_.reset(new AXTreeArcSerializer(this)); | 411 current_tree_serializer_.reset(new AXTreeArcSerializer(this)); |
| 367 root_id_ = -1; | 412 root_id_ = -1; |
| 368 focused_node_id_ = -1; | 413 focused_node_id_ = -1; |
| 369 extensions::AutomationEventRouter* router = | 414 extensions::AutomationEventRouter* router = |
| 370 extensions::AutomationEventRouter::GetInstance(); | 415 extensions::AutomationEventRouter::GetInstance(); |
| 371 router->DispatchTreeDestroyedEvent(tree_id_, nullptr); | 416 if (!router) |
| 417 return; |
| 418 |
| 419 router->DispatchTreeDestroyedEvent(tree_id(), nullptr); |
| 372 } | 420 } |
| 373 | 421 |
| 374 } // namespace arc | 422 } // namespace arc |
| OLD | NEW |