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

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: Review comments. 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 "ui/accessibility/ax_action_data.h" 12 #include "ui/accessibility/ax_action_data.h"
13 #include "ui/accessibility/ax_node_data.h" 13 #include "ui/accessibility/ax_node_data.h"
14 #include "ui/accessibility/platform/ax_platform_node_delegate.h" 14 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
15 #include "ui/base/l10n/l10n_util.h"
15 #import "ui/gfx/mac/coordinate_conversion.h" 16 #import "ui/gfx/mac/coordinate_conversion.h"
17 #include "ui/strings/grit/ui_strings.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 {
25 ui::AXEvent value; 27 ui::AXEvent value;
(...skipping 151 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"},
dmazzoni 2017/01/13 18:11:23 Any documentation on this, or did you get it from
Patti Lor 2017/01/16 02:59:50 Whoops, you're right - deleted. I think I original
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 // Since tabs use the Radio Button role on Mac, the standard way to set them
385 // is via the value attribute rather than the selected attribute.
386 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] &&
387 node_->GetData().role == ui::AX_ROLE_TAB) {
388 return !node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED);
389 }
390
382 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] || 391 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] ||
383 [attributeName isEqualToString:NSAccessibilitySelectedTextAttribute]) 392 [attributeName isEqualToString:NSAccessibilitySelectedTextAttribute]) {
384 return !ui::AXNodeData::IsFlagSet(node_->GetData().state, 393 return !ui::AXNodeData::IsFlagSet(node_->GetData().state,
385 ui::AX_STATE_READ_ONLY); 394 ui::AX_STATE_READ_ONLY);
395 }
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
400 data.value = base::SysNSStringToUTF16(value); 410 // Check for attributes first. Only the |data.action| should be set here - any
401 if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { 411 // type-specific information, if needed, should be set below.
402 data.action = ui::AX_ACTION_SET_VALUE; 412 if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
403 } else if ([attribute 413 data.action = node_->GetData().role == ui::AX_ROLE_TAB
404 isEqualToString:NSAccessibilitySelectedTextAttribute]) { 414 ? ui::AX_ACTION_SET_SELECTION
405 data.action = ui::AX_ACTION_REPLACE_SELECTED_TEXT; 415 : ui::AX_ACTION_SET_VALUE;
406 } 416 } else if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) {
407 } else if ([value isKindOfClass:[NSNumber class]]) { 417 data.action = ui::AX_ACTION_REPLACE_SELECTED_TEXT;
408 if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { 418 } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
419 if ([value isKindOfClass:[NSNumber class]]) {
409 data.action = 420 data.action =
410 [value boolValue] ? ui::AX_ACTION_FOCUS : ui::AX_ACTION_BLUR; 421 [value boolValue] ? ui::AX_ACTION_FOCUS : ui::AX_ACTION_BLUR;
411 } 422 }
412 } 423 }
413 424
425 // Set type-specific information as necessary for actions set above.
426 if ([value isKindOfClass:[NSString class]])
427 data.value = base::SysNSStringToUTF16(value);
428
414 if (data.action != ui::AX_ACTION_NONE) 429 if (data.action != ui::AX_ACTION_NONE)
415 node_->GetDelegate()->AccessibilityPerformAction(data); 430 node_->GetDelegate()->AccessibilityPerformAction(data);
416 431
417 // TODO(patricialor): Plumb through all the other writable attributes as 432 // TODO(patricialor): Plumb through all the other writable attributes as
418 // specified in accessibilityIsAttributeSettable. 433 // specified in accessibilityIsAttributeSettable.
419 } 434 }
420 435
421 - (id)accessibilityAttributeValue:(NSString*)attribute { 436 - (id)accessibilityAttributeValue:(NSString*)attribute {
422 SEL selector = NSSelectorFromString(attribute); 437 SEL selector = NSSelectorFromString(attribute);
423 if ([self respondsToSelector:selector]) 438 if ([self respondsToSelector:selector])
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 ui::AX_STATE_PROTECTED)) 476 ui::AX_STATE_PROTECTED))
462 return NSAccessibilitySecureTextFieldSubrole; 477 return NSAccessibilitySecureTextFieldSubrole;
463 break; 478 break;
464 default: 479 default:
465 break; 480 break;
466 } 481 }
467 return [AXPlatformNodeCocoa nativeSubroleFromAXRole:role]; 482 return [AXPlatformNodeCocoa nativeSubroleFromAXRole:role];
468 } 483 }
469 484
470 - (NSString*)AXRoleDescription { 485 - (NSString*)AXRoleDescription {
486 switch (node_->GetData().role) {
487 case ui::AX_ROLE_TAB:
488 // There is no NSAccessibilityTabRole or similar (AXRadioButton is used
489 // instead). Do the same as NSTabView and put "tab" in the description.
490 return [l10n_util::GetNSStringWithFixup(IDS_ACCNAME_TAB_ROLE_DESCRIPTION)
491 lowercaseString];
492 default:
493 break;
494 }
471 return NSAccessibilityRoleDescription([self AXRole], [self AXSubrole]); 495 return NSAccessibilityRoleDescription([self AXRole], [self AXSubrole]);
472 } 496 }
473 497
474 - (NSValue*)AXSize { 498 - (NSValue*)AXSize {
475 return [NSValue valueWithSize:self.boundsInScreen.size]; 499 return [NSValue valueWithSize:self.boundsInScreen.size];
476 } 500 }
477 501
478 - (NSString*)AXTitle { 502 - (NSString*)AXTitle {
479 return [self getStringAttribute:ui::AX_ATTR_NAME]; 503 return [self getStringAttribute:ui::AX_ATTR_NAME];
480 } 504 }
481 505
482 - (NSString*)AXValue { 506 - (id)AXValue {
507 if (node_->GetData().role == ui::AX_ROLE_TAB)
508 return [self AXSelected];
483 return [self getStringAttribute:ui::AX_ATTR_VALUE]; 509 return [self getStringAttribute:ui::AX_ATTR_VALUE];
484 } 510 }
485 511
486 - (NSValue*)AXEnabled { 512 - (NSValue*)AXEnabled {
487 return [NSNumber 513 return [NSNumber
488 numberWithBool:!ui::AXNodeData::IsFlagSet(node_->GetData().state, 514 numberWithBool:!ui::AXNodeData::IsFlagSet(node_->GetData().state,
489 ui::AX_STATE_DISABLED)]; 515 ui::AX_STATE_DISABLED)];
490 } 516 }
491 517
492 - (NSValue*)AXFocused { 518 - (NSValue*)AXFocused {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 int beginSelectionIndex = (end > start && !isReversed) ? start : end; 569 int beginSelectionIndex = (end > start && !isReversed) ? start : end;
544 return [NSValue 570 return [NSValue
545 valueWithRange:NSMakeRange(beginSelectionIndex, abs(end - start))]; 571 valueWithRange:NSMakeRange(beginSelectionIndex, abs(end - start))];
546 } 572 }
547 573
548 - (NSValue*)AXVisibleCharacterRange { 574 - (NSValue*)AXVisibleCharacterRange {
549 return [NSValue 575 return [NSValue
550 valueWithRange:NSMakeRange(0, [[self AXNumberOfCharacters] intValue])]; 576 valueWithRange:NSMakeRange(0, [[self AXNumberOfCharacters] intValue])];
551 } 577 }
552 578
579 // Misc NSAccessibility attributes.
580
581 - (NSNumber*)AXSelected {
582 return [NSNumber
583 numberWithBool:node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED)];
584 }
585
553 @end 586 @end
554 587
555 namespace ui { 588 namespace ui {
556 589
557 // static 590 // static
558 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) { 591 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
559 AXPlatformNodeBase* node = new AXPlatformNodeMac(); 592 AXPlatformNodeBase* node = new AXPlatformNodeMac();
560 node->Init(delegate); 593 node->Init(delegate);
561 return node; 594 return node;
562 } 595 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 } 629 }
597 NotifyMacEvent(native_node_, event_type); 630 NotifyMacEvent(native_node_, event_type);
598 } 631 }
599 632
600 int AXPlatformNodeMac::GetIndexInParent() { 633 int AXPlatformNodeMac::GetIndexInParent() {
601 // TODO(dmazzoni): implement this. http://crbug.com/396137 634 // TODO(dmazzoni): implement this. http://crbug.com/396137
602 return -1; 635 return -1;
603 } 636 }
604 637
605 } // namespace ui 638 } // namespace ui
OLDNEW
« no previous file with comments | « content/test/data/accessibility/aria/aria-tabpanel-expected-mac.txt ('k') | ui/strings/ui_strings.grd » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698