diff options
author | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-29 15:08:39 +0000 |
---|---|---|
committer | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-29 15:08:39 +0000 |
commit | 5123b36099d7dfff857b2d170e8593f60b77df12 (patch) | |
tree | 73ce8d7e827a933cb6a032c72d2d50a8e42bf6b9 /content/browser | |
parent | b6e695a9c6fa185592c01bd16fcbd7b95296e571 (diff) | |
download | chromium_src-5123b36099d7dfff857b2d170e8593f60b77df12.zip chromium_src-5123b36099d7dfff857b2d170e8593f60b77df12.tar.gz chromium_src-5123b36099d7dfff857b2d170e8593f60b77df12.tar.bz2 |
Add support for a few more Mac accessibility attributes.
Includes ARIA live regions, required fields, sliders and other range
controls, and list subroles. Interestingly, implementing the list subroles
causes VoiceOver to stop making lists hierarchical, which is one thing that
made Chrome seem weird compared to Safari.
BUG=none
TEST=manual testing
Review URL: http://codereview.chromium.org/8036022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@103275 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
-rw-r--r-- | content/browser/accessibility/browser_accessibility_cocoa.mm | 146 |
1 files changed, 131 insertions, 15 deletions
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm index 7f605e5..fd765730 100644 --- a/content/browser/accessibility/browser_accessibility_cocoa.mm +++ b/content/browser/accessibility/browser_accessibility_cocoa.mm @@ -21,7 +21,6 @@ // this object. extern "C" void NSAccessibilityUnregisterUniqueIdForUIElement(id element); -typedef WebAccessibility::IntAttribute IntAttribute; typedef WebAccessibility::StringAttribute StringAttribute; namespace { @@ -183,6 +182,8 @@ static const AttributeToMethodNameEntry attributeToMethodNameContainer[] = { { NSAccessibilityEnabledAttribute, @"enabled" }, { NSAccessibilityFocusedAttribute, @"focused" }, { NSAccessibilityHelpAttribute, @"help" }, + { NSAccessibilityMaxValueAttribute, @"maxValue" }, + { NSAccessibilityMinValueAttribute, @"minValue" }, { NSAccessibilityNumberOfCharactersAttribute, @"numberOfCharacters" }, { NSAccessibilityParentAttribute, @"parent" }, { NSAccessibilityPositionAttribute, @"position" }, @@ -198,7 +199,14 @@ static const AttributeToMethodNameEntry attributeToMethodNameContainer[] = { { NSAccessibilityValueAttribute, @"value" }, { NSAccessibilityVisibleCharacterRangeAttribute, @"visibleCharacterRange" }, { NSAccessibilityWindowAttribute, @"window" }, + { @"AXAccessKey", @"accessKey" }, + { @"AXARIAAtomic", @"ariaAtomic" }, + { @"AXARIABusy", @"ariaBusy" }, + { @"AXARIALive", @"ariaLive" }, + { @"AXARIARelevant", @"ariaRelevant" }, { @"AXLoaded", @"loaded" }, + { @"AXLoadingProgress", @"loadingProgress" }, + { @"AXRequired", @"required" }, { @"AXVisited", @"visited" }, }; @@ -262,6 +270,38 @@ NSDictionary* attributeToMethodNameMap = nil; [super dealloc]; } +- (NSString*)accessKey { + return NSStringForStringAttribute( + browserAccessibility_->string_attributes(), + WebAccessibility::ATTR_ACCESS_KEY); +} + +- (NSNumber*)ariaAtomic { + bool boolValue = false; + browserAccessibility_->GetBoolAttribute( + WebAccessibility::ATTR_LIVE_ATOMIC, &boolValue); + return [NSNumber numberWithBool:boolValue]; +} + +- (NSNumber*)ariaBusy { + bool boolValue = false; + browserAccessibility_->GetBoolAttribute( + WebAccessibility::ATTR_LIVE_BUSY, &boolValue); + return [NSNumber numberWithBool:boolValue]; +} + +- (NSString*)ariaLive { + return NSStringForStringAttribute( + browserAccessibility_->string_attributes(), + WebAccessibility::ATTR_LIVE_STATUS); +} + +- (NSString*)ariaRelevant { + return NSStringForStringAttribute( + browserAccessibility_->string_attributes(), + WebAccessibility::ATTR_LIVE_RELEVANT); +} + // Returns an array of BrowserAccessibilityCocoa objects, representing the // accessibility children of this object. - (NSArray*)children { @@ -350,6 +390,31 @@ NSDictionary* attributeToMethodNameMap = nil; return [NSNumber numberWithBool:YES]; } +- (NSNumber*)loadingProgress { + float floatValue = 0.0; + browserAccessibility_->GetFloatAttribute( + WebAccessibility::ATTR_DOC_LOADING_PROGRESS, &floatValue); + return [NSNumber numberWithFloat:floatValue]; +} + +- (NSNumber*)maxValue { + float floatValue = 0.0; + browserAccessibility_->GetFloatAttribute( + WebAccessibility::ATTR_MAX_VALUE_FOR_RANGE, &floatValue); + return [NSNumber numberWithFloat:floatValue]; +} + +- (NSNumber*)minValue { + float floatValue = 0.0; + browserAccessibility_->GetFloatAttribute( + WebAccessibility::ATTR_MIN_VALUE_FOR_RANGE, &floatValue); + return [NSNumber numberWithFloat:floatValue]; +} + +- (NSNumber*)numberOfCharacters { + return [NSNumber numberWithInt:browserAccessibility_->value().length()]; +} + // The origin of this accessibility object in the page's document. // This is relative to webkit's top-left origin, not Cocoa's // bottom-left origin. @@ -358,10 +423,6 @@ NSDictionary* attributeToMethodNameMap = nil; browserAccessibility_->location().y()); } -- (NSNumber*)numberOfCharacters { - return [NSNumber numberWithInt:browserAccessibility_->value().length()]; -} - - (id)parent { // A nil parent means we're the root. if (browserAccessibility_->parent()) { @@ -377,6 +438,11 @@ NSDictionary* attributeToMethodNameMap = nil; return [NSValue valueWithPoint:[delegate_ accessibilityPointInScreen:self]]; } +- (NSNumber*)required { + return [NSNumber numberWithBool: + !GetState(browserAccessibility_, WebAccessibility::STATE_REQUIRED)]; +} + // Returns a string indicating the role of this object. - (NSString*)role { WebAccessibility::Role browserAccessibilityRole = @@ -456,22 +522,28 @@ NSDictionary* attributeToMethodNameMap = nil; // Returns a subrole based upon the role. - (NSString*) subrole { - // TODO: support attachments - // TODO: support lists -> NSAccessibilityContentListSubrole || - // NSAccessibilityDefinitionListSubrole - WebAccessibility::Role browserAccessibilityRole = - static_cast<WebAccessibility::Role>( browserAccessibility_->role()); - + static_cast<WebAccessibility::Role>(browserAccessibility_->role()); if (browserAccessibilityRole == WebAccessibility::ROLE_TEXT_FIELD && GetState(browserAccessibility_, WebAccessibility::STATE_PROTECTED)) { return @"AXSecureTextField"; } + NSString* htmlTag = NSStringForStringAttribute( + browserAccessibility_->string_attributes(), + WebAccessibility::ATTR_HTML_TAG); + + if (browserAccessibilityRole == WebAccessibility::ROLE_LIST) { + if ([htmlTag isEqualToString:@"ul"] || + [htmlTag isEqualToString:@"ol"]) { + return @"AXContentList"; + } else if ([htmlTag isEqualToString:@"dl"]) { + return @"AXDefinitionList"; + } + } std::map<WebAccessibility::Role, NSString*>::iterator it = webAccessibilityToNativeSubrole.find(browserAccessibilityRole); - if (it != webAccessibilityToNativeSubrole.end()) return it->second; else @@ -527,9 +599,24 @@ NSDictionary* attributeToMethodNameMap = nil; return @""; } else if ([role isEqualToString:NSAccessibilityCheckBoxRole] || [role isEqualToString:NSAccessibilityRadioButtonRole]) { - return [NSNumber numberWithInt:GetState( - browserAccessibility_, WebAccessibility::STATE_CHECKED) ? 1 : 0]; + int checkOrRadioValue = GetState( + browserAccessibility_, WebAccessibility::STATE_CHECKED) ? 1 : 0; + bool mixed = false; + browserAccessibility_->GetBoolAttribute( + WebAccessibility::ATTR_BUTTON_MIXED, &mixed); + if (mixed) + checkOrRadioValue = 2; + return [NSNumber numberWithInt:checkOrRadioValue]; + } else if ([role isEqualToString:NSAccessibilityProgressIndicatorRole] || + [role isEqualToString:NSAccessibilitySliderRole] || + [role isEqualToString:NSAccessibilityScrollBarRole]) { + float floatValue; + if (browserAccessibility_->GetFloatAttribute( + WebAccessibility::ATTR_VALUE_FOR_RANGE, &floatValue)) { + return [NSNumber numberWithFloat:floatValue]; + } } + return base::SysUTF16ToNSString(browserAccessibility_->value()); } @@ -721,6 +808,8 @@ NSDictionary* attributeToMethodNameMap = nil; NSAccessibilityValueAttribute, NSAccessibilityWindowAttribute, NSAccessibilityURLAttribute, + @"AXAccessKey", + @"AXRequired", @"AXVisited", nil]; @@ -732,7 +821,10 @@ NSDictionary* attributeToMethodNameMap = nil; NSAccessibilityRowsAttribute, nil]]; } else if ([role isEqualToString:@"AXWebArea"]) { - [ret addObject:@"AXLoaded"]; + [ret addObjectsFromArray:[NSArray arrayWithObjects: + @"AXLoaded", + @"AXLoadingProgress", + nil]]; } else if ([role isEqualToString:NSAccessibilityTextFieldRole] || [role isEqualToString:NSAccessibilityTextAreaRole]) { [ret addObjectsFromArray:[NSArray arrayWithObjects: @@ -744,6 +836,30 @@ NSDictionary* attributeToMethodNameMap = nil; nil]]; } else if ([role isEqualToString:NSAccessibilityTabGroupRole]) { [ret addObject:NSAccessibilityTabsAttribute]; + } else if ([role isEqualToString:NSAccessibilityProgressIndicatorRole] || + [role isEqualToString:NSAccessibilitySliderRole] || + [role isEqualToString:NSAccessibilityScrollBarRole]) { + [ret addObjectsFromArray:[NSArray arrayWithObjects: + NSAccessibilityMaxValueAttribute, + NSAccessibilityMinValueAttribute, + nil]]; + } + + // Live regions. + string16 s; + if (browserAccessibility_->GetStringAttribute( + WebAccessibility::ATTR_LIVE_STATUS, &s)) { + [ret addObjectsFromArray:[NSArray arrayWithObjects: + @"AXARIALive", + @"AXARIARelevant", + nil]]; + } + if (browserAccessibility_->GetStringAttribute( + WebAccessibility::ATTR_CONTAINER_LIVE_STATUS, &s)) { + [ret addObjectsFromArray:[NSArray arrayWithObjects: + @"AXARIAAtomic", + @"AXARIABusy", + nil]]; } return ret; |