Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Side by Side Diff: content/browser/accessibility/browser_accessibility_manager_mac.mm

Issue 2917363002: Automatically fire AX events on Mac based on tree changes (Closed)
Patch Set: Fix accidental shadowing of BrowserAccessibilityManager::OnAtomicUpdateFinished, caught by browser … Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "content/browser/accessibility/browser_accessibility_manager_mac.h" 5 #include "content/browser/accessibility/browser_accessibility_manager_mac.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #import "base/mac/mac_util.h" 8 #import "base/mac/mac_util.h"
9 #import "base/mac/scoped_nsobject.h" 9 #import "base/mac/scoped_nsobject.h"
10 #import "base/mac/sdk_forward_declarations.h" 10 #import "base/mac/sdk_forward_declarations.h"
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 } 355 }
356 356
357 void BrowserAccessibilityManagerMac::OnAccessibilityEvents( 357 void BrowserAccessibilityManagerMac::OnAccessibilityEvents(
358 const std::vector<AXEventNotificationDetails>& details) { 358 const std::vector<AXEventNotificationDetails>& details) {
359 text_edits_.clear(); 359 text_edits_.clear();
360 // Call the base method last as it might delete the tree if it receives an 360 // Call the base method last as it might delete the tree if it receives an
361 // invalid message. 361 // invalid message.
362 BrowserAccessibilityManager::OnAccessibilityEvents(details); 362 BrowserAccessibilityManager::OnAccessibilityEvents(details);
363 } 363 }
364 364
365 void BrowserAccessibilityManagerMac::OnTreeDataChanged(
366 ui::AXTree* tree,
367 const ui::AXTreeData& old_tree_data,
368 const ui::AXTreeData& new_tree_data) {
369 BrowserAccessibilityManager::OnTreeDataChanged(tree, old_tree_data,
370 new_tree_data);
371 if (new_tree_data.loaded && !old_tree_data.loaded)
372 tree_events_[tree->root()->id()].insert(ui::AX_EVENT_LOAD_COMPLETE);
373 if (new_tree_data.sel_anchor_object_id !=
374 old_tree_data.sel_anchor_object_id ||
375 new_tree_data.sel_anchor_offset != old_tree_data.sel_anchor_offset ||
376 new_tree_data.sel_anchor_affinity != old_tree_data.sel_anchor_affinity ||
377 new_tree_data.sel_focus_object_id != old_tree_data.sel_focus_object_id ||
378 new_tree_data.sel_focus_offset != old_tree_data.sel_focus_offset ||
379 new_tree_data.sel_focus_affinity != old_tree_data.sel_focus_affinity) {
380 tree_events_[tree->root()->id()].insert(
381 ui::AX_EVENT_DOCUMENT_SELECTION_CHANGED);
382 }
383 }
384
365 void BrowserAccessibilityManagerMac::OnNodeDataWillChange( 385 void BrowserAccessibilityManagerMac::OnNodeDataWillChange(
366 ui::AXTree* tree, 386 ui::AXTree* tree,
367 const ui::AXNodeData& old_node_data, 387 const ui::AXNodeData& old_node_data,
368 const ui::AXNodeData& new_node_data) { 388 const ui::AXNodeData& new_node_data) {
369 BrowserAccessibilityManager::OnNodeDataWillChange(tree, old_node_data, 389 BrowserAccessibilityManager::OnNodeDataWillChange(tree, old_node_data,
370 new_node_data); 390 new_node_data);
371 391
372 // Starting from OS X 10.11, if the user has edited some text we need to 392 // Starting from OS X 10.11, if the user has edited some text we need to
373 // dispatch the actual text that changed on the value changed notification. 393 // dispatch the actual text that changed on the value changed notification.
374 // We run this code on all OS X versions to get the highest test coverage. 394 // We run this code on all OS X versions to get the highest test coverage.
(...skipping 29 matching lines...) Expand all
404 while (i < old_text.length() && i < new_text.length() && 424 while (i < old_text.length() && i < new_text.length() &&
405 old_text[i] == new_text[i]) { 425 old_text[i] == new_text[i]) {
406 ++i; 426 ++i;
407 } 427 }
408 size_t length = (old_text.length() - i) - (new_text.length() - i); 428 size_t length = (old_text.length() - i) - (new_text.length() - i);
409 base::string16 deleted_text = old_text.substr(i, length); 429 base::string16 deleted_text = old_text.substr(i, length);
410 text_edits_[new_node_data.id] = deleted_text; 430 text_edits_[new_node_data.id] = deleted_text;
411 } 431 }
412 } 432 }
413 433
434 bool IsContainerWithSelectableChildrenRole(ui::AXRole role) {
435 switch (role) {
436 case ui::AX_ROLE_COMBO_BOX:
437 case ui::AX_ROLE_GRID:
438 case ui::AX_ROLE_LIST_BOX:
439 case ui::AX_ROLE_MENU:
440 case ui::AX_ROLE_MENU_BAR:
441 case ui::AX_ROLE_RADIO_GROUP:
442 case ui::AX_ROLE_TAB_LIST:
443 case ui::AX_ROLE_TOOLBAR:
444 case ui::AX_ROLE_TREE:
445 case ui::AX_ROLE_TREE_GRID:
446 return true;
447 default:
448 return false;
449 }
450 }
451
452 bool IsRowContainer(ui::AXRole role) {
453 switch (role) {
454 case ui::AX_ROLE_TREE:
455 case ui::AX_ROLE_TREE_GRID:
456 case ui::AX_ROLE_GRID:
457 case ui::AX_ROLE_TABLE:
458 return true;
459 default:
460 return false;
461 }
462 }
463
464 void BrowserAccessibilityManagerMac::OnStateChanged(ui::AXTree* tree,
465 ui::AXNode* node,
466 ui::AXState state,
467 bool new_value) {
468 BrowserAccessibilityManager::OnStateChanged(tree, node, state, new_value);
469 if (state == ui::AX_STATE_EXPANDED) {
470 if (node->data().role == ui::AX_ROLE_ROW ||
471 node->data().role == ui::AX_ROLE_TREE_ITEM) {
472 if (new_value)
473 tree_events_[node->id()].insert(ui::AX_EVENT_ROW_EXPANDED);
474 else
475 tree_events_[node->id()].insert(ui::AX_EVENT_ROW_COLLAPSED);
476 ui::AXNode* container = node;
477 while (container && !IsRowContainer(container->data().role))
478 container = container->parent();
479 if (container)
480 tree_events_[container->id()].insert(ui::AX_EVENT_ROW_COUNT_CHANGED);
481 } else {
482 tree_events_[node->id()].insert(ui::AX_EVENT_EXPANDED_CHANGED);
483 }
484 }
485 if (state == ui::AX_STATE_SELECTED) {
486 ui::AXNode* container = node;
487 while (container &&
488 !IsContainerWithSelectableChildrenRole(container->data().role))
489 container = container->parent();
490 if (container)
491 tree_events_[container->id()].insert(
492 ui::AX_EVENT_SELECTED_CHILDREN_CHANGED);
493 }
494 }
495
496 void BrowserAccessibilityManagerMac::OnStringAttributeChanged(
497 ui::AXTree* tree,
498 ui::AXNode* node,
499 ui::AXStringAttribute attr,
500 const std::string& old_value,
501 const std::string& new_value) {
502 BrowserAccessibilityManager::OnStringAttributeChanged(tree, node, attr,
503 old_value, new_value);
504 switch (attr) {
505 case ui::AX_ATTR_VALUE:
506 tree_events_[node->id()].insert(ui::AX_EVENT_VALUE_CHANGED);
507 break;
508 case ui::AX_ATTR_ARIA_INVALID_VALUE:
509 tree_events_[node->id()].insert(ui::AX_EVENT_INVALID_STATUS_CHANGED);
510 break;
511 case ui::AX_ATTR_LIVE_STATUS:
512 tree_events_[node->id()].insert(ui::AX_EVENT_LIVE_REGION_CREATED);
513 break;
514 default:
515 break;
516 }
517 }
518
519 void BrowserAccessibilityManagerMac::OnIntAttributeChanged(
520 ui::AXTree* tree,
521 ui::AXNode* node,
522 ui::AXIntAttribute attr,
523 int32_t old_value,
524 int32_t new_value) {
525 BrowserAccessibilityManager::OnIntAttributeChanged(tree, node, attr,
526 old_value, new_value);
527 switch (attr) {
528 case ui::AX_ATTR_CHECKED_STATE:
529 tree_events_[node->id()].insert(ui::AX_EVENT_VALUE_CHANGED);
530 break;
531 case ui::AX_ATTR_ACTIVEDESCENDANT_ID:
532 tree_events_[node->id()].insert(ui::AX_EVENT_ACTIVEDESCENDANTCHANGED);
533 break;
534 case ui::AX_ATTR_INVALID_STATE:
535 tree_events_[node->id()].insert(ui::AX_EVENT_INVALID_STATUS_CHANGED);
536 break;
537 default:
538 break;
539 }
540 }
541
542 void BrowserAccessibilityManagerMac::OnFloatAttributeChanged(
543 ui::AXTree* tree,
544 ui::AXNode* node,
545 ui::AXFloatAttribute attr,
546 float old_value,
547 float new_value) {
548 BrowserAccessibilityManager::OnFloatAttributeChanged(tree, node, attr,
549 old_value, new_value);
550 if (attr == ui::AX_ATTR_VALUE_FOR_RANGE)
551 tree_events_[node->id()].insert(ui::AX_EVENT_VALUE_CHANGED);
552 }
553
554 void BrowserAccessibilityManagerMac::OnAtomicUpdateFinished(
555 ui::AXTree* tree,
556 bool root_changed,
557 const std::vector<Change>& changes) {
558 BrowserAccessibilityManager::OnAtomicUpdateFinished(tree, root_changed,
559 changes);
560 for (const auto& change : changes) {
561 if ((change.type == NODE_CREATED || change.type == SUBTREE_CREATED) &&
562 change.node->data().HasStringAttribute(ui::AX_ATTR_LIVE_STATUS)) {
563 if (change.node->data().role == ui::AX_ROLE_ALERT)
564 tree_events_[change.node->id()].insert(ui::AX_EVENT_ALERT);
565 else
566 tree_events_[change.node->id()].insert(
567 ui::AX_EVENT_LIVE_REGION_CREATED);
568 continue;
569 }
570 if (change.node->data().HasStringAttribute(
571 ui::AX_ATTR_CONTAINER_LIVE_STATUS)) {
572 ui::AXNode* live_root = change.node;
573 while (live_root &&
574 !live_root->data().HasStringAttribute(ui::AX_ATTR_LIVE_STATUS))
575 live_root = live_root->parent();
576 if (live_root)
577 tree_events_[live_root->id()].insert(ui::AX_EVENT_LIVE_REGION_CHANGED);
578 }
579 }
580 }
581
414 NSDictionary* BrowserAccessibilityManagerMac:: 582 NSDictionary* BrowserAccessibilityManagerMac::
415 GetUserInfoForSelectedTextChangedNotification() { 583 GetUserInfoForSelectedTextChangedNotification() {
416 NSMutableDictionary* user_info = [[[NSMutableDictionary alloc] init] 584 NSMutableDictionary* user_info = [[[NSMutableDictionary alloc] init]
417 autorelease]; 585 autorelease];
418 [user_info setObject:@YES forKey:NSAccessibilityTextStateSyncKey]; 586 [user_info setObject:@YES forKey:NSAccessibilityTextStateSyncKey];
419 [user_info setObject:@(AXTextStateChangeTypeUnknown) 587 [user_info setObject:@(AXTextStateChangeTypeUnknown)
420 forKey:NSAccessibilityTextStateChangeTypeKey]; 588 forKey:NSAccessibilityTextStateChangeTypeKey];
421 [user_info setObject:@(AXTextSelectionDirectionUnknown) 589 [user_info setObject:@(AXTextSelectionDirectionUnknown)
422 forKey:NSAccessibilityTextSelectionDirection]; 590 forKey:NSAccessibilityTextSelectionDirection];
423 [user_info setObject:@(AXTextSelectionGranularityUnknown) 591 [user_info setObject:@(AXTextSelectionGranularityUnknown)
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 NSAccessibilityTextChangeValues : changes, 642 NSAccessibilityTextChangeValues : changes,
475 NSAccessibilityTextChangeElement : native_node 643 NSAccessibilityTextChangeElement : native_node
476 }; 644 };
477 } 645 }
478 646
479 NSView* BrowserAccessibilityManagerMac::GetParentView() { 647 NSView* BrowserAccessibilityManagerMac::GetParentView() {
480 return delegate() ? delegate()->AccessibilityGetAcceleratedWidget() : nullptr; 648 return delegate() ? delegate()->AccessibilityGetAcceleratedWidget() : nullptr;
481 } 649 }
482 650
483 } // namespace content 651 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698