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

Side by Side Diff: ui/accessibility/platform/ax_platform_node_mac.mm

Issue 2578303003: a11y: Add a11y information to views::Tab and manually ignore its a11y children. (Closed)
Patch Set: Fix DumpAccessibilityTreeTest.AccessibilityAriaTabPanel. Created 3 years, 11 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 #import "ui/accessibility/platform/ax_platform_node_mac.h" 5 #import "ui/accessibility/platform/ax_platform_node_mac.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include "base/macros.h" 10 #include "base/macros.h"
11 #include "base/strings/sys_string_conversions.h" 11 #include "base/strings/sys_string_conversions.h"
12 #include "chrome/grit/generated_resources.h"
12 #include "ui/accessibility/ax_action_data.h" 13 #include "ui/accessibility/ax_action_data.h"
13 #include "ui/accessibility/ax_node_data.h" 14 #include "ui/accessibility/ax_node_data.h"
14 #include "ui/accessibility/platform/ax_platform_node_delegate.h" 15 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
16 #include "ui/base/l10n/l10n_util.h"
15 #import "ui/gfx/mac/coordinate_conversion.h" 17 #import "ui/gfx/mac/coordinate_conversion.h"
16 18
17 namespace { 19 namespace {
18 20
19 struct RoleMapEntry { 21 struct RoleMapEntry {
20 ui::AXRole value; 22 ui::AXRole value;
21 NSString* nativeValue; 23 NSString* nativeValue;
22 }; 24 };
23 25
24 struct EventMapEntry { 26 struct EventMapEntry {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 {ui::AX_ROLE_MAIN, @"AXLandmarkMain"}, 179 {ui::AX_ROLE_MAIN, @"AXLandmarkMain"},
178 {ui::AX_ROLE_MARQUEE, @"AXApplicationMarquee"}, 180 {ui::AX_ROLE_MARQUEE, @"AXApplicationMarquee"},
179 {ui::AX_ROLE_MATH, @"AXDocumentMath"}, 181 {ui::AX_ROLE_MATH, @"AXDocumentMath"},
180 {ui::AX_ROLE_NAVIGATION, @"AXLandmarkNavigation"}, 182 {ui::AX_ROLE_NAVIGATION, @"AXLandmarkNavigation"},
181 {ui::AX_ROLE_NOTE, @"AXDocumentNote"}, 183 {ui::AX_ROLE_NOTE, @"AXDocumentNote"},
182 {ui::AX_ROLE_REGION, @"AXDocumentRegion"}, 184 {ui::AX_ROLE_REGION, @"AXDocumentRegion"},
183 {ui::AX_ROLE_SEARCH, @"AXLandmarkSearch"}, 185 {ui::AX_ROLE_SEARCH, @"AXLandmarkSearch"},
184 {ui::AX_ROLE_SEARCH_BOX, @"AXSearchField"}, 186 {ui::AX_ROLE_SEARCH_BOX, @"AXSearchField"},
185 {ui::AX_ROLE_STATUS, @"AXApplicationStatus"}, 187 {ui::AX_ROLE_STATUS, @"AXApplicationStatus"},
186 {ui::AX_ROLE_SWITCH, @"AXSwitch"}, 188 {ui::AX_ROLE_SWITCH, @"AXSwitch"},
189 {ui::AX_ROLE_TAB, @"AXTab"},
187 {ui::AX_ROLE_TAB_PANEL, @"AXTabPanel"}, 190 {ui::AX_ROLE_TAB_PANEL, @"AXTabPanel"},
188 {ui::AX_ROLE_TIMER, @"AXApplicationTimer"}, 191 {ui::AX_ROLE_TIMER, @"AXApplicationTimer"},
189 {ui::AX_ROLE_TOGGLE_BUTTON, @"AXToggleButton"}, 192 {ui::AX_ROLE_TOGGLE_BUTTON, @"AXToggleButton"},
190 {ui::AX_ROLE_TOOLTIP, @"AXUserInterfaceTooltip"}, 193 {ui::AX_ROLE_TOOLTIP, @"AXUserInterfaceTooltip"},
191 {ui::AX_ROLE_TREE_ITEM, NSAccessibilityOutlineRowSubrole}, 194 {ui::AX_ROLE_TREE_ITEM, NSAccessibilityOutlineRowSubrole},
192 }; 195 };
193 196
194 RoleMap subrole_map; 197 RoleMap subrole_map;
195 for (size_t i = 0; i < arraysize(subroles); ++i) 198 for (size_t i = 0; i < arraysize(subroles); ++i)
196 subrole_map[subroles[i].value] = subroles[i].nativeValue; 199 subrole_map[subroles[i].value] = subroles[i].nativeValue;
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 default: 365 default:
363 break; 366 break;
364 } 367 }
365 return axAttributes.autorelease(); 368 return axAttributes.autorelease();
366 } 369 }
367 370
368 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName { 371 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName {
369 // Allow certain attributes to be written via an accessibility client. A 372 // Allow certain attributes to be written via an accessibility client. A
370 // writable attribute will only appear as such if the accessibility element 373 // writable attribute will only appear as such if the accessibility element
371 // has a value set for that attribute. 374 // has a value set for that attribute.
372 if ([attributeName isEqualToString:NSAccessibilitySelectedAttribute] || 375 if ([attributeName
373 [attributeName
374 isEqualToString:NSAccessibilitySelectedChildrenAttribute] || 376 isEqualToString:NSAccessibilitySelectedChildrenAttribute] ||
375 [attributeName 377 [attributeName
376 isEqualToString:NSAccessibilitySelectedTextRangeAttribute] || 378 isEqualToString:NSAccessibilitySelectedTextRangeAttribute] ||
377 [attributeName 379 [attributeName
378 isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) { 380 isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) {
379 return NO; 381 return NO;
380 } 382 }
381 383
384 // Tabs are a special case. For whatever reason,
tapted 2017/01/03 00:29:27 The reason might be that in Cocoa, using role=AXRa
Patti Lor 2017/01/06 02:02:29 Done.
385 // NSAccessibilitySelectedAttribute isn't used for them, so allow editing of
386 // the value attribute to select unselected tabs instead.
387 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] &&
388 node_->GetData().role == ui::AX_ROLE_TAB) {
389 return !node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED);
390 }
391
382 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] || 392 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] ||
383 [attributeName isEqualToString:NSAccessibilitySelectedTextAttribute]) 393 [attributeName isEqualToString:NSAccessibilitySelectedTextAttribute])
384 return !ui::AXNodeData::IsFlagSet(node_->GetData().state, 394 return !ui::AXNodeData::IsFlagSet(node_->GetData().state,
385 ui::AX_STATE_READ_ONLY); 395 ui::AX_STATE_READ_ONLY);
386 396
387 if ([attributeName isEqualToString:NSAccessibilityFocusedAttribute]) { 397 if ([attributeName isEqualToString:NSAccessibilityFocusedAttribute]) {
388 return ui::AXNodeData::IsFlagSet(node_->GetData().state, 398 return ui::AXNodeData::IsFlagSet(node_->GetData().state,
389 ui::AX_STATE_FOCUSABLE); 399 ui::AX_STATE_FOCUSABLE);
390 } 400 }
391 401
392 // TODO(patricialor): Add callbacks for updating the above attributes except 402 // TODO(patricialor): Add callbacks for updating the above attributes except
393 // NSAccessibilityValueAttribute and return YES. 403 // NSAccessibilityValueAttribute and return YES.
394 return NO; 404 return NO;
395 } 405 }
396 406
397 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute { 407 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute {
398 ui::AXActionData data; 408 ui::AXActionData data;
399 if ([value isKindOfClass:[NSString class]]) { 409 if ([value isKindOfClass:[NSString class]]) {
400 data.value = base::SysNSStringToUTF16(value); 410 data.value = base::SysNSStringToUTF16(value);
401 if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { 411 if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
402 data.action = ui::AX_ACTION_SET_VALUE; 412 // Tabs have no other way to set their selected state via a11y, so use the
413 // value attribute here.
414 data.action = node_->GetData().role == ui::AX_ROLE_TAB
415 ? ui::AX_ACTION_SET_SELECTION
416 : ui::AX_ACTION_SET_VALUE;
403 } else if ([attribute 417 } else if ([attribute
404 isEqualToString:NSAccessibilitySelectedTextAttribute]) { 418 isEqualToString:NSAccessibilitySelectedTextAttribute]) {
405 data.action = ui::AX_ACTION_REPLACE_SELECTED_TEXT; 419 data.action = ui::AX_ACTION_REPLACE_SELECTED_TEXT;
406 } 420 }
407 } else if ([value isKindOfClass:[NSNumber class]]) { 421 } else if ([value isKindOfClass:[NSNumber class]]) {
408 if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { 422 if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
409 data.action = 423 data.action =
410 [value boolValue] ? ui::AX_ACTION_FOCUS : ui::AX_ACTION_BLUR; 424 [value boolValue] ? ui::AX_ACTION_FOCUS : ui::AX_ACTION_BLUR;
411 } 425 }
412 } 426 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 ui::AX_STATE_PROTECTED)) 475 ui::AX_STATE_PROTECTED))
462 return NSAccessibilitySecureTextFieldSubrole; 476 return NSAccessibilitySecureTextFieldSubrole;
463 break; 477 break;
464 default: 478 default:
465 break; 479 break;
466 } 480 }
467 return [AXPlatformNodeCocoa nativeSubroleFromAXRole:role]; 481 return [AXPlatformNodeCocoa nativeSubroleFromAXRole:role];
468 } 482 }
469 483
470 - (NSString*)AXRoleDescription { 484 - (NSString*)AXRoleDescription {
485 ui::AXRole role = node_->GetData().role;
486 switch (role) {
tapted 2017/01/03 00:29:27 nit: switch (node_->GetData().role) {
Patti Lor 2017/01/06 02:02:29 Done.
487 case ui::AX_ROLE_TAB:
488 return l10n_util::GetNSStringWithFixup(IDS_ACCNAME_TAB);
Patti Lor 2016/12/30 00:35:02 There's no "NSAccessibilityTabRole" or similar, so
tapted 2017/01/03 00:29:27 Can we move IDS_ACCNAME_TAB to ui_resources.grd? I
Patti Lor 2017/01/06 02:02:29 A recent patch (https://codereview.chromium.org/25
489 default:
490 break;
491 }
471 return NSAccessibilityRoleDescription([self AXRole], [self AXSubrole]); 492 return NSAccessibilityRoleDescription([self AXRole], [self AXSubrole]);
472 } 493 }
473 494
474 - (NSValue*)AXSize { 495 - (NSValue*)AXSize {
475 return [NSValue valueWithSize:self.boundsInScreen.size]; 496 return [NSValue valueWithSize:self.boundsInScreen.size];
476 } 497 }
477 498
478 - (NSString*)AXTitle { 499 - (NSString*)AXTitle {
479 return [self getStringAttribute:ui::AX_ATTR_NAME]; 500 return [self getStringAttribute:ui::AX_ATTR_NAME];
480 } 501 }
481 502
482 - (NSString*)AXValue { 503 - (NSString*)AXValue {
504 if (node_->GetData().role == ui::AX_ROLE_TAB)
505 return [[self AXSelected] stringValue];
483 return [self getStringAttribute:ui::AX_ATTR_VALUE]; 506 return [self getStringAttribute:ui::AX_ATTR_VALUE];
484 } 507 }
485 508
486 - (NSValue*)AXEnabled { 509 - (NSValue*)AXEnabled {
487 return [NSNumber 510 return [NSNumber
488 numberWithBool:!ui::AXNodeData::IsFlagSet(node_->GetData().state, 511 numberWithBool:!ui::AXNodeData::IsFlagSet(node_->GetData().state,
489 ui::AX_STATE_DISABLED)]; 512 ui::AX_STATE_DISABLED)];
490 } 513 }
491 514
492 - (NSValue*)AXFocused { 515 - (NSValue*)AXFocused {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 int beginSelectionIndex = (end > start && !isReversed) ? start : end; 566 int beginSelectionIndex = (end > start && !isReversed) ? start : end;
544 return [NSValue 567 return [NSValue
545 valueWithRange:NSMakeRange(beginSelectionIndex, abs(end - start))]; 568 valueWithRange:NSMakeRange(beginSelectionIndex, abs(end - start))];
546 } 569 }
547 570
548 - (NSValue*)AXVisibleCharacterRange { 571 - (NSValue*)AXVisibleCharacterRange {
549 return [NSValue 572 return [NSValue
550 valueWithRange:NSMakeRange(0, [[self AXNumberOfCharacters] intValue])]; 573 valueWithRange:NSMakeRange(0, [[self AXNumberOfCharacters] intValue])];
551 } 574 }
552 575
576 // Misc NSAccessibility attributes.
577
578 - (NSNumber*)AXSelected {
Patti Lor 2016/12/30 00:35:02 Not sure if we should leave this in; I can't tell
tapted 2017/01/03 00:29:27 This looks good. I think it's fine to add anythin
Patti Lor 2017/01/06 02:02:29 Acknowledged.
579 return [NSNumber
580 numberWithBool:node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED)];
581 }
582
553 @end 583 @end
554 584
555 namespace ui { 585 namespace ui {
556 586
557 // static 587 // static
558 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) { 588 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
559 AXPlatformNodeBase* node = new AXPlatformNodeMac(); 589 AXPlatformNodeBase* node = new AXPlatformNodeMac();
560 node->Init(delegate); 590 node->Init(delegate);
561 return node; 591 return node;
562 } 592 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 } 626 }
597 NotifyMacEvent(native_node_, event_type); 627 NotifyMacEvent(native_node_, event_type);
598 } 628 }
599 629
600 int AXPlatformNodeMac::GetIndexInParent() { 630 int AXPlatformNodeMac::GetIndexInParent() {
601 // TODO(dmazzoni): implement this. http://crbug.com/396137 631 // TODO(dmazzoni): implement this. http://crbug.com/396137
602 return -1; 632 return -1;
603 } 633 }
604 634
605 } // namespace ui 635 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698