Bug 1611428: Add accessibilityLabel function to support aria-label on MacOS. r=eeejay,Jamie

Differential Revision: https://phabricator.services.mozilla.com/D62470

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Morgan Reschenberg 2020-02-14 21:20:27 +00:00
parent 665fc1b7b5
commit 7c8049bbaf
7 changed files with 71 additions and 13 deletions

View File

@ -24,8 +24,9 @@ uint64_t NativeState() const;
/*
* Set aName to the name of the proxied accessible.
* Return the ENameValueFlag passed from Accessible::Name
*/
void Name(nsString& aName) const;
uint32_t Name(nsString& aName) const;
/*
* Set aValue to the value of the proxied accessible.

View File

@ -102,11 +102,12 @@ mozilla::ipc::IPCResult DocAccessibleChild::RecvNativeState(const uint64_t& aID,
}
mozilla::ipc::IPCResult DocAccessibleChild::RecvName(const uint64_t& aID,
nsString* aName) {
nsString* aName,
uint32_t* aFlag) {
Accessible* acc = IdToAccessible(aID);
if (!acc) return IPC_OK();
acc->Name(*aName);
*aFlag = acc->Name(*aName);
return IPC_OK();
}

View File

@ -55,8 +55,8 @@ class DocAccessibleChild : public DocAccessibleChildBase {
/*
* Get the name for the accessible with given id.
*/
virtual mozilla::ipc::IPCResult RecvName(const uint64_t& aID,
nsString* aName) override;
virtual mozilla::ipc::IPCResult RecvName(const uint64_t& aID, nsString* aName,
uint32_t* aFlag) override;
virtual mozilla::ipc::IPCResult RecvValue(const uint64_t& aID,
nsString* aValue) override;

View File

@ -126,7 +126,7 @@ child:
// Accessible
nested(inside_sync) sync State(uint64_t aID) returns(uint64_t states);
nested(inside_sync) sync NativeState(uint64_t aID) returns(uint64_t states);
nested(inside_sync) sync Name(uint64_t aID) returns(nsString name);
nested(inside_sync) sync Name(uint64_t aID) returns(nsString name, uint32_t flag);
nested(inside_sync) sync Value(uint64_t aID) returns(nsString value);
nested(inside_sync) sync Help(uint64_t aID) returns(nsString help);
nested(inside_sync) sync Description(uint64_t aID) returns(nsString desc);

View File

@ -30,8 +30,10 @@ uint64_t ProxyAccessible::NativeState() const {
return state;
}
void ProxyAccessible::Name(nsString& aName) const {
Unused << mDoc->SendName(mID, &aName);
uint32_t ProxyAccessible::Name(nsString& aName) const {
uint32_t flag;
Unused << mDoc->SendName(mID, &aName, &flag);
return flag;
}
void ProxyAccessible::Value(nsString& aValue) const {

View File

@ -118,20 +118,26 @@ static ProxyAccessible* GetProxyFor(DocAccessibleParent* aDoc,
return aDoc->GetAccessible(id);
}
void ProxyAccessible::Name(nsString& aName) const {
uint32_t ProxyAccessible::Name(nsString& aName) const {
/* The return values here exist only to match behvaiour required
* by the header declaration of this function. On Mac, we'd like
* to return the associated ENameValueFlag, but we don't have
* access to that here, so we return a dummy eNameOK value instead.
*/
aName.Truncate();
RefPtr<IAccessible> acc;
if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
return;
return eNameOK;
}
BSTR result;
HRESULT hr = acc->get_accName(kChildIdSelf, &result);
_bstr_t resultWrap(result, false);
if (FAILED(hr)) {
return;
return eNameOK;
}
aName = (wchar_t*)resultWrap;
return eNameOK;
}
void ProxyAccessible::Value(nsString& aValue) const {

View File

@ -274,14 +274,25 @@ static inline NSMutableArray* ConvertToNSArray(nsTArray<ProxyAccessible*>& aArra
if ([attribute isEqualToString:NSAccessibilityTopLevelUIElementAttribute]) return [self window];
if ([attribute isEqualToString:NSAccessibilityTitleAttribute]) return [self title];
if ([attribute isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
/* If our accessible is labelled by more than one item, its label
* should be set by accessibilityLabel instead of here, so we return nil.
*/
if (accWrap) {
Relation rel = accWrap->RelationByType(RelationType::LABELLED_BY);
Accessible* tempAcc = rel.Next();
return tempAcc ? GetNativeFromGeckoAccessible(tempAcc) : nil;
if (tempAcc && !rel.Next()) {
return GetNativeFromGeckoAccessible(tempAcc);
} else {
return nil;
}
}
nsTArray<ProxyAccessible*> rel = proxy->RelationByType(RelationType::LABELLED_BY);
ProxyAccessible* tempProxy = rel.SafeElementAt(0);
return tempProxy ? GetNativeFromProxy(tempProxy) : nil;
if (tempProxy && rel.Length() <= 1) {
return GetNativeFromProxy(tempProxy);
} else {
return nil;
}
}
if ([attribute isEqualToString:NSAccessibilityHelpAttribute]) return [self help];
if ([attribute isEqualToString:NSAccessibilityOrientationAttribute]) return [self orientation];
@ -474,6 +485,43 @@ static inline NSMutableArray* ConvertToNSArray(nsTArray<ProxyAccessible*>& aArra
return NSAccessibilityActionDescription(action);
}
- (NSString*)accessibilityLabel {
AccessibleWrap* accWrap = [self getGeckoAccessible];
ProxyAccessible* proxy = [self getProxyAccessible];
if (!accWrap && !proxy) {
return nil;
}
/* If our accessible is labelled by exactly one item, or if its
* name is obtained from a subtree, we should let
* NSAccessibilityTitleUIElementAttribute determine its label. */
if (accWrap) {
nsAutoString name;
ENameValueFlag flag = accWrap->Name(name);
if (flag == eNameFromSubtree) {
return nil;
}
Relation rel = accWrap->RelationByType(RelationType::LABELLED_BY);
if (rel.Next() && !rel.Next()) {
return nil;
}
} else if (proxy) {
nsAutoString name;
uint32_t flag = proxy->Name(name);
if (flag == eNameFromSubtree) {
return nil;
}
nsTArray<ProxyAccessible*> rels = proxy->RelationByType(RelationType::LABELLED_BY);
if (rels.Length() == 1) {
return nil;
}
}
return [self title];
}
- (void)accessibilityPerformAction:(NSString*)action {
}