diff --git a/accessible/src/atk/AccessibleWrap.cpp b/accessible/src/atk/AccessibleWrap.cpp index f5d99f06459..4495bebdc7d 100644 --- a/accessible/src/atk/AccessibleWrap.cpp +++ b/accessible/src/atk/AccessibleWrap.cpp @@ -871,6 +871,32 @@ refStateSetCB(AtkObject *aAtkObj) return state_set; } +static void +UpdateAtkRelation(RelationType aType, Accessible* aAcc, + AtkRelationType aAtkType, AtkRelationSet* aAtkSet) +{ + if (aAtkType == ATK_RELATION_NULL) + return; + + AtkRelation* atkRelation = + atk_relation_set_get_relation_by_type(aAtkSet, aAtkType); + if (atkRelation) + atk_relation_set_remove(aAtkSet, atkRelation); + + Relation rel(aAcc->RelationByType(aType)); + nsTArray targets; + Accessible* tempAcc = nullptr; + while ((tempAcc = rel.Next())) + targets.AppendElement(AccessibleWrap::GetAtkObject(tempAcc)); + + if (targets.Length()) { + atkRelation = atk_relation_new(targets.Elements(), + targets.Length(), aAtkType); + atk_relation_set_add(aAtkSet, atkRelation); + g_object_unref(atkRelation); + } +} + AtkRelationSet * refRelationSetCB(AtkObject *aAtkObj) { @@ -881,46 +907,12 @@ refRelationSetCB(AtkObject *aAtkObj) if (!accWrap) return relation_set; - // Keep in sync with AtkRelationType enum. - static const RelationType relationTypes[] = { - RelationType::CONTROLLED_BY, - RelationType::CONTROLLER_FOR, - RelationType::LABEL_FOR, - RelationType::LABELLED_BY, - RelationType::MEMBER_OF, - RelationType::NODE_CHILD_OF, - RelationType::FLOWS_TO, - RelationType::FLOWS_FROM, - RelationType::SUBWINDOW_OF, - RelationType::EMBEDS, - RelationType::EMBEDDED_BY, - RelationType::POPUP_FOR, - RelationType::PARENT_WINDOW_OF, - RelationType::DESCRIBED_BY, - RelationType::DESCRIPTION_FOR, - RelationType::NODE_PARENT_OF - }; +#define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \ + UpdateAtkRelation(RelationType::geckoType, accWrap, atkType, relation_set); - for (uint32_t i = 0; i < ArrayLength(relationTypes); i++) { - // Shift to 1 to skip ATK_RELATION_NULL. - AtkRelationType atkType = static_cast(i + 1); - AtkRelation* atkRelation = - atk_relation_set_get_relation_by_type(relation_set, atkType); - if (atkRelation) - atk_relation_set_remove(relation_set, atkRelation); +#include "RelationTypeMap.h" - Relation rel(accWrap->RelationByType(relationTypes[i])); - nsTArray targets; - Accessible* tempAcc = nullptr; - while ((tempAcc = rel.Next())) - targets.AppendElement(AccessibleWrap::GetAtkObject(tempAcc)); - - if (targets.Length()) { - atkRelation = atk_relation_new(targets.Elements(), targets.Length(), atkType); - atk_relation_set_add(relation_set, atkRelation); - g_object_unref(atkRelation); - } - } +#undef RELATIONTYPE return relation_set; } diff --git a/accessible/src/base/RoleAsserts.cpp b/accessible/src/base/Asserts.cpp similarity index 64% rename from accessible/src/base/RoleAsserts.cpp rename to accessible/src/base/Asserts.cpp index 34a9a203941..b97a48ec488 100644 --- a/accessible/src/base/RoleAsserts.cpp +++ b/accessible/src/base/Asserts.cpp @@ -4,7 +4,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "nsIAccessibleRelation.h" #include "nsIAccessibleRole.h" +#include "RelationType.h" #include "Role.h" using namespace mozilla::a11y; @@ -15,3 +17,10 @@ using namespace mozilla::a11y; "internal and xpcom roles differ!"); #include "RoleMap.h" #undef ROLE + +#define RELATIONTYPE(geckoType, stringType, atkType, msaaType, ia2Type) \ + static_assert(static_cast(RelationType::geckoType) \ + == static_cast(nsIAccessibleRelation::RELATION_ ## geckoType), \ + "internal and xpcom relations differ!"); +#include "RelationTypeMap.h" +#undef RELATIONTYPE diff --git a/accessible/src/base/RelationTypeMap.h b/accessible/src/base/RelationTypeMap.h new file mode 100644 index 00000000000..a2bdb47d01a --- /dev/null +++ b/accessible/src/base/RelationTypeMap.h @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Usage: declare the macro RELATIONTYPE()with the following arguments: + * RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) + */ + +RELATIONTYPE(LABELLED_BY, + "labelled by", + ATK_RELATION_LABELLED_BY, + NAVRELATION_LABELLED_BY, + IA2_RELATION_LABELLED_BY) + +RELATIONTYPE(LABEL_FOR, + "label for", + ATK_RELATION_LABEL_FOR, + NAVRELATION_LABEL_FOR, + IA2_RELATION_LABEL_FOR) + +RELATIONTYPE(DESCRIBED_BY, + "described by", + ATK_RELATION_DESCRIBED_BY, + NAVRELATION_DESCRIBED_BY, + IA2_RELATION_DESCRIBED_BY) + +RELATIONTYPE(DESCRIPTION_FOR, + "description for", + ATK_RELATION_DESCRIPTION_FOR, + NAVRELATION_DESCRIPTION_FOR, + IA2_RELATION_DESCRIPTION_FOR) + +RELATIONTYPE(NODE_CHILD_OF, + "node child of", + ATK_RELATION_NODE_CHILD_OF, + NAVRELATION_NODE_CHILD_OF, + IA2_RELATION_NODE_CHILD_OF) + +RELATIONTYPE(NODE_PARENT_OF, + "node parent of", + ATK_RELATION_NODE_PARENT_OF, + NAVRELATION_NODE_PARENT_OF, + IA2_RELATION_NODE_PARENT_OF) + +RELATIONTYPE(CONTROLLED_BY, + "controlled by", + ATK_RELATION_CONTROLLED_BY, + NAVRELATION_CONTROLLED_BY, + IA2_RELATION_CONTROLLED_BY) + +RELATIONTYPE(CONTROLLER_FOR, + "controller for", + ATK_RELATION_CONTROLLER_FOR, + NAVRELATION_CONTROLLER_FOR, + IA2_RELATION_CONTROLLER_FOR) + +RELATIONTYPE(FLOWS_TO, + "flows to", + ATK_RELATION_FLOWS_TO, + NAVRELATION_FLOWS_TO, + IA2_RELATION_FLOWS_TO) + +RELATIONTYPE(FLOWS_FROM, + "flows from", + ATK_RELATION_FLOWS_FROM, + NAVRELATION_FLOWS_FROM, + IA2_RELATION_FLOWS_FROM) + +RELATIONTYPE(MEMBER_OF, + "member of", + ATK_RELATION_MEMBER_OF, + NAVRELATION_MEMBER_OF, + IA2_RELATION_MEMBER_OF) + +RELATIONTYPE(SUBWINDOW_OF, + "subwindow of", + ATK_RELATION_SUBWINDOW_OF, + NAVRELATION_SUBWINDOW_OF, + IA2_RELATION_SUBWINDOW_OF) + +RELATIONTYPE(EMBEDS, + "embeds", + ATK_RELATION_EMBEDS, + NAVRELATION_EMBEDS, + IA2_RELATION_EMBEDS) + +RELATIONTYPE(EMBEDDED_BY, + "embedded by", + ATK_RELATION_EMBEDDED_BY, + NAVRELATION_EMBEDDED_BY, + IA2_RELATION_EMBEDDED_BY) + +RELATIONTYPE(POPUP_FOR, + "popup for", + ATK_RELATION_POPUP_FOR, + NAVRELATION_POPUP_FOR, + IA2_RELATION_POPUP_FOR) + +RELATIONTYPE(PARENT_WINDOW_OF, + "parent window of", + ATK_RELATION_PARENT_WINDOW_OF, + NAVRELATION_PARENT_WINDOW_OF, + IA2_RELATION_PARENT_WINDOW_OF) + +RELATIONTYPE(DEFAULT_BUTTON, + "default button", + ATK_RELATION_NULL, + NAVRELATION_DEFAULT_BUTTON, + IA2_RELATION_NULL) diff --git a/accessible/src/base/moz.build b/accessible/src/base/moz.build index 109bd4617ab..1593ad9e902 100644 --- a/accessible/src/base/moz.build +++ b/accessible/src/base/moz.build @@ -37,6 +37,7 @@ CPP_SOURCES += [ 'AccIterator.cpp', 'ARIAMap.cpp', 'ARIAStateMap.cpp', + 'Asserts.cpp', 'DocManager.cpp', 'EventQueue.cpp', 'Filters.cpp', @@ -49,7 +50,6 @@ CPP_SOURCES += [ 'nsCoreUtils.cpp', 'nsEventShell.cpp', 'nsTextEquivUtils.cpp', - 'RoleAsserts.cpp', 'SelectionManager.cpp', 'StyleInfo.cpp', 'TextAttrs.cpp', diff --git a/accessible/src/base/nsAccessibilityService.cpp b/accessible/src/base/nsAccessibilityService.cpp index 62a0d472aab..5804fb43528 100644 --- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -713,13 +713,22 @@ NS_IMETHODIMP nsAccessibilityService::GetStringRelationType(uint32_t aRelationType, nsAString& aString) { - if (aRelationType >= ArrayLength(kRelationTypeNames)) { - aString.AssignLiteral("unknown"); + NS_ENSURE_ARG(aRelationType <= static_cast(RelationType::LAST)); + +#define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \ + case RelationType::geckoType: \ + aString.AssignLiteral(geckoTypeName); \ return NS_OK; + + RelationType relationType = static_cast(aRelationType); + switch (relationType) { +#include "RelationTypeMap.h" + default: + aString.AssignLiteral("unknown"); + return NS_OK; } - CopyUTF8toUTF16(kRelationTypeNames[aRelationType], aString); - return NS_OK; +#undef RELATIONTYPE } NS_IMETHODIMP diff --git a/accessible/src/base/nsAccessibilityService.h b/accessible/src/base/nsAccessibilityService.h index 3b7469f984b..fe30989c33e 100644 --- a/accessible/src/base/nsAccessibilityService.h +++ b/accessible/src/base/nsAccessibilityService.h @@ -332,29 +332,5 @@ static const char kEventTypeNames[][40] = { "virtual cursor changed" // EVENT_VIRTUALCURSOR_CHANGED }; -/** - * Map nsIAccessibleRelation constants to strings. Used by - * nsIAccessibleRetrieval::getStringRelationType() method. - */ -static const char kRelationTypeNames[][20] = { - "labelled by", // RELATION_LABELLED_BY - "label for", // RELATION_LABEL_FOR - "described by", // RELATION_DESCRIBED_BY - "description for", // RELATION_DESCRIPTION_FOR - "node child of", // RELATION_NODE_CHILD_OF - "node parent of", // RELATION_NODE_PARENT_OF - "controlled by", // RELATION_CONTROLLED_BY - "controller for", // RELATION_CONTROLLER_FOR - "flows to", // RELATION_FLOWS_TO - "flows from", // RELATION_FLOWS_FROM - "member of", // RELATION_MEMBER_OF - "subwindow of", // RELATION_SUBWINDOW_OF - "embeds", // RELATION_EMBEDS - "embedded by", // RELATION_EMBEDDED_BY - "popup for", // RELATION_POPUP_FOR - "parent window of", // RELATION_PARENT_WINDOW_OF - "default button" // RELATION_DEFAULT_BUTTON -}; - #endif /* __nsIAccessibilityService_h__ */ diff --git a/accessible/src/windows/ia2/ia2Accessible.cpp b/accessible/src/windows/ia2/ia2Accessible.cpp index 08cb8f64dd6..7deaaf4e9af 100644 --- a/accessible/src/windows/ia2/ia2Accessible.cpp +++ b/accessible/src/windows/ia2/ia2Accessible.cpp @@ -60,8 +60,11 @@ ia2Accessible::get_nRelations(long* aNRelations) if (acc->IsDefunct()) return CO_E_OBJNOTCONNECTED; - for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2); idx++) { - Relation rel = acc->RelationByType(sRelationTypesForIA2[idx]); + for (uint32_t idx = 0; idx < ArrayLength(sRelationTypePairs); idx++) { + if (sRelationTypePairs[idx].second == IA2_RELATION_NULL) + continue; + + Relation rel = acc->RelationByType(sRelationTypePairs[idx].first); if (rel.Next()) (*aNRelations)++; } @@ -85,8 +88,11 @@ ia2Accessible::get_relation(long aRelationIndex, return CO_E_OBJNOTCONNECTED; long relIdx = 0; - for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2); idx++) { - RelationType relationType = sRelationTypesForIA2[idx]; + for (uint32_t idx = 0; idx < ArrayLength(sRelationTypePairs); idx++) { + if (sRelationTypePairs[idx].second == IA2_RELATION_NULL) + continue; + + RelationType relationType = sRelationTypePairs[idx].first; Relation rel = acc->RelationByType(relationType); nsRefPtr ia2Relation = new ia2AccessibleRelation(relationType, &rel); @@ -120,9 +126,12 @@ ia2Accessible::get_relations(long aMaxRelations, if (acc->IsDefunct()) return CO_E_OBJNOTCONNECTED; - for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2) && + for (uint32_t idx = 0; idx < ArrayLength(sRelationTypePairs) && *aNRelations < aMaxRelations; idx++) { - RelationType relationType = sRelationTypesForIA2[idx]; + if (sRelationTypePairs[idx].second == IA2_RELATION_NULL) + continue; + + RelationType relationType = sRelationTypePairs[idx].first; Relation rel = acc->RelationByType(relationType); nsRefPtr ia2Rel = new ia2AccessibleRelation(relationType, &rel); diff --git a/accessible/src/windows/ia2/ia2AccessibleRelation.cpp b/accessible/src/windows/ia2/ia2AccessibleRelation.cpp index aeba6ab4958..488acc87cb7 100644 --- a/accessible/src/windows/ia2/ia2AccessibleRelation.cpp +++ b/accessible/src/windows/ia2/ia2AccessibleRelation.cpp @@ -33,7 +33,7 @@ IMPL_IUNKNOWN_QUERY_TAIL // IAccessibleRelation STDMETHODIMP -ia2AccessibleRelation::get_relationType(BSTR *aRelationType) +ia2AccessibleRelation::get_relationType(BSTR* aRelationType) { A11Y_TRYBLOCK_BEGIN @@ -42,55 +42,13 @@ ia2AccessibleRelation::get_relationType(BSTR *aRelationType) *aRelationType = nullptr; +#define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \ + case RelationType::geckoType: \ + *aRelationType = ::SysAllocString(ia2Type); \ + break; + switch (mType) { - case RelationType::CONTROLLED_BY: - *aRelationType = ::SysAllocString(IA2_RELATION_CONTROLLED_BY); - break; - case RelationType::CONTROLLER_FOR: - *aRelationType = ::SysAllocString(IA2_RELATION_CONTROLLER_FOR); - break; - case RelationType::DESCRIBED_BY: - *aRelationType = ::SysAllocString(IA2_RELATION_DESCRIBED_BY); - break; - case RelationType::DESCRIPTION_FOR: - *aRelationType = ::SysAllocString(IA2_RELATION_DESCRIPTION_FOR); - break; - case RelationType::EMBEDDED_BY: - *aRelationType = ::SysAllocString(IA2_RELATION_EMBEDDED_BY); - break; - case RelationType::EMBEDS: - *aRelationType = ::SysAllocString(IA2_RELATION_EMBEDS); - break; - case RelationType::FLOWS_FROM: - *aRelationType = ::SysAllocString(IA2_RELATION_FLOWS_FROM); - break; - case RelationType::FLOWS_TO: - *aRelationType = ::SysAllocString(IA2_RELATION_FLOWS_TO); - break; - case RelationType::LABEL_FOR: - *aRelationType = ::SysAllocString(IA2_RELATION_LABEL_FOR); - break; - case RelationType::LABELLED_BY: - *aRelationType = ::SysAllocString(IA2_RELATION_LABELED_BY); - break; - case RelationType::MEMBER_OF: - *aRelationType = ::SysAllocString(IA2_RELATION_MEMBER_OF); - break; - case RelationType::NODE_CHILD_OF: - *aRelationType = ::SysAllocString(IA2_RELATION_NODE_CHILD_OF); - break; - case RelationType::NODE_PARENT_OF: - *aRelationType = ::SysAllocString(IA2_RELATION_NODE_PARENT_OF); - break; - case RelationType::PARENT_WINDOW_OF: - *aRelationType = ::SysAllocString(IA2_RELATION_PARENT_WINDOW_OF); - break; - case RelationType::POPUP_FOR: - *aRelationType = ::SysAllocString(IA2_RELATION_POPUP_FOR); - break; - case RelationType::SUBWINDOW_OF: - *aRelationType = ::SysAllocString(IA2_RELATION_SUBWINDOW_OF); - break; +#include "RelationTypeMap.h" } return *aRelationType ? S_OK : E_OUTOFMEMORY; @@ -166,4 +124,3 @@ ia2AccessibleRelation::get_targets(long aMaxTargets, IUnknown **aTargets, A11Y_TRYBLOCK_END } - diff --git a/accessible/src/windows/ia2/ia2AccessibleRelation.h b/accessible/src/windows/ia2/ia2AccessibleRelation.h index 3f6602ca3bf..17bab435e15 100644 --- a/accessible/src/windows/ia2/ia2AccessibleRelation.h +++ b/accessible/src/windows/ia2/ia2AccessibleRelation.h @@ -12,6 +12,7 @@ #include "IUnknownImpl.h" #include "nsIAccessibleRelation.h" +#include #include "nsTArray.h" #include "AccessibleRelation.h" @@ -60,27 +61,20 @@ private: /** - * Relations exposed to IAccessible2. + * Gecko to IAccessible2 relation types map. */ -static const RelationType sRelationTypesForIA2[] = { - RelationType::LABELLED_BY, - RelationType::LABEL_FOR, - RelationType::DESCRIBED_BY, - RelationType::DESCRIPTION_FOR, - RelationType::NODE_CHILD_OF, - RelationType::NODE_PARENT_OF, - RelationType::CONTROLLED_BY, - RelationType::CONTROLLER_FOR, - RelationType::FLOWS_TO, - RelationType::FLOWS_FROM, - RelationType::MEMBER_OF, - RelationType::SUBWINDOW_OF, - RelationType::EMBEDS, - RelationType::EMBEDDED_BY, - RelationType::POPUP_FOR, - RelationType::PARENT_WINDOW_OF + +const WCHAR *const IA2_RELATION_NULL = L""; + +#define RELATIONTYPE(geckoType, name, atkType, msaaType, ia2Type) \ + std::pair(RelationType::geckoType, ia2Type), + +static const std::pair sRelationTypePairs[] = { +#include "RelationTypeMap.h" }; +#undef RELATIONTYPE + } // namespace a11y } // namespace mozilla diff --git a/accessible/src/windows/msaa/AccessibleWrap.cpp b/accessible/src/windows/msaa/AccessibleWrap.cpp index 1844c6fbe4d..f14a534c877 100644 --- a/accessible/src/windows/msaa/AccessibleWrap.cpp +++ b/accessible/src/windows/msaa/AccessibleWrap.cpp @@ -898,6 +898,11 @@ AccessibleWrap::accNavigate( Accessible* navAccessible = nullptr; Maybe xpRelation; +#define RELATIONTYPE(geckoType, stringType, atkType, msaaType, ia2Type) \ + case msaaType: \ + xpRelation.construct(RelationType::geckoType); \ + break; + switch(navDir) { case NAVDIR_FIRSTCHILD: if (!nsAccUtils::MustPrune(accessible)) @@ -920,62 +925,14 @@ AccessibleWrap::accNavigate( return E_NOTIMPL; // MSAA relationship extensions to accNavigate - case NAVRELATION_CONTROLLED_BY: - xpRelation.construct(RelationType::CONTROLLED_BY); - break; - case NAVRELATION_CONTROLLER_FOR: - xpRelation.construct(RelationType::CONTROLLER_FOR); - break; - case NAVRELATION_LABEL_FOR: - xpRelation.construct(RelationType::LABEL_FOR); - break; - case NAVRELATION_LABELLED_BY: - xpRelation.construct(RelationType::LABELLED_BY); - break; - case NAVRELATION_MEMBER_OF: - xpRelation.construct(RelationType::MEMBER_OF); - break; - case NAVRELATION_NODE_CHILD_OF: - xpRelation.construct(RelationType::NODE_CHILD_OF); - break; - case NAVRELATION_FLOWS_TO: - xpRelation.construct(RelationType::FLOWS_TO); - break; - case NAVRELATION_FLOWS_FROM: - xpRelation.construct(RelationType::FLOWS_FROM); - break; - case NAVRELATION_SUBWINDOW_OF: - xpRelation.construct(RelationType::SUBWINDOW_OF); - break; - case NAVRELATION_EMBEDS: - xpRelation.construct(RelationType::EMBEDS); - break; - case NAVRELATION_EMBEDDED_BY: - xpRelation.construct(RelationType::EMBEDDED_BY); - break; - case NAVRELATION_POPUP_FOR: - xpRelation.construct(RelationType::POPUP_FOR); - break; - case NAVRELATION_PARENT_WINDOW_OF: - xpRelation.construct(RelationType::PARENT_WINDOW_OF); - break; - case NAVRELATION_DEFAULT_BUTTON: - xpRelation.construct(RelationType::DEFAULT_BUTTON); - break; - case NAVRELATION_DESCRIBED_BY: - xpRelation.construct(RelationType::DESCRIBED_BY); - break; - case NAVRELATION_DESCRIPTION_FOR: - xpRelation.construct(RelationType::DESCRIPTION_FOR); - break; - case NAVRELATION_NODE_PARENT_OF: - xpRelation.construct(RelationType::NODE_PARENT_OF); - break; +#include "RelationTypeMap.h" default: return E_INVALIDARG; } +#undef RELATIONTYPE + pvarEndUpAt->vt = VT_EMPTY; if (!xpRelation.empty()) {