summaryrefslogtreecommitdiffstats
path: root/accessible/windows/ia2
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/windows/ia2')
-rw-r--r--accessible/windows/ia2/ia2Accessible.cpp810
-rw-r--r--accessible/windows/ia2/ia2Accessible.h122
-rw-r--r--accessible/windows/ia2/ia2AccessibleAction.cpp188
-rw-r--r--accessible/windows/ia2/ia2AccessibleAction.h93
-rw-r--r--accessible/windows/ia2/ia2AccessibleComponent.cpp127
-rw-r--r--accessible/windows/ia2/ia2AccessibleComponent.h38
-rw-r--r--accessible/windows/ia2/ia2AccessibleEditableText.cpp153
-rw-r--r--accessible/windows/ia2/ia2AccessibleEditableText.h56
-rw-r--r--accessible/windows/ia2/ia2AccessibleHyperlink.cpp205
-rw-r--r--accessible/windows/ia2/ia2AccessibleHyperlink.h51
-rw-r--r--accessible/windows/ia2/ia2AccessibleHypertext.cpp93
-rw-r--r--accessible/windows/ia2/ia2AccessibleHypertext.h43
-rw-r--r--accessible/windows/ia2/ia2AccessibleImage.cpp119
-rw-r--r--accessible/windows/ia2/ia2AccessibleImage.h40
-rw-r--r--accessible/windows/ia2/ia2AccessibleRelation.cpp125
-rw-r--r--accessible/windows/ia2/ia2AccessibleRelation.h85
-rw-r--r--accessible/windows/ia2/ia2AccessibleTable.cpp747
-rw-r--r--accessible/windows/ia2/ia2AccessibleTable.h176
-rw-r--r--accessible/windows/ia2/ia2AccessibleTableCell.cpp257
-rw-r--r--accessible/windows/ia2/ia2AccessibleTableCell.h69
-rw-r--r--accessible/windows/ia2/ia2AccessibleText.cpp598
-rw-r--r--accessible/windows/ia2/ia2AccessibleText.h275
-rw-r--r--accessible/windows/ia2/ia2AccessibleValue.cpp151
-rw-r--r--accessible/windows/ia2/ia2AccessibleValue.h41
-rw-r--r--accessible/windows/ia2/moz.build58
25 files changed, 4720 insertions, 0 deletions
diff --git a/accessible/windows/ia2/ia2Accessible.cpp b/accessible/windows/ia2/ia2Accessible.cpp
new file mode 100644
index 000000000..c72719b51
--- /dev/null
+++ b/accessible/windows/ia2/ia2Accessible.cpp
@@ -0,0 +1,810 @@
+/* -*- 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/. */
+
+#include "AccessibleWrap.h"
+
+#include "Accessible2_i.c"
+#include "Accessible2_2_i.c"
+#include "Accessible2_3_i.c"
+#include "AccessibleRole.h"
+#include "AccessibleStates.h"
+
+#include "Compatibility.h"
+#include "ia2AccessibleRelation.h"
+#include "IUnknownImpl.h"
+#include "nsCoreUtils.h"
+#include "nsIAccessibleTypes.h"
+#include "mozilla/a11y/PDocAccessible.h"
+#include "Relation.h"
+#include "TextRange-inl.h"
+#include "nsAccessibilityService.h"
+
+#include "nsIPersistentProperties2.h"
+#include "nsISimpleEnumerator.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+
+template<typename String> static void EscapeAttributeChars(String& aStr);
+
+////////////////////////////////////////////////////////////////////////////////
+// ia2Accessible
+////////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP
+ia2Accessible::QueryInterface(REFIID iid, void** ppv)
+{
+ if (!ppv)
+ return E_INVALIDARG;
+
+ *ppv = nullptr;
+
+ if (IID_IAccessible2_3 == iid)
+ *ppv = static_cast<IAccessible2_3*>(this);
+ else if (IID_IAccessible2_2 == iid)
+ *ppv = static_cast<IAccessible2_2*>(this);
+ else if (IID_IAccessible2 == iid && !Compatibility::IsIA2Off())
+ *ppv = static_cast<IAccessible2*>(this);
+
+ if (*ppv) {
+ (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// IAccessible2
+
+STDMETHODIMP
+ia2Accessible::get_nRelations(long* aNRelations)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aNRelations)
+ return E_INVALIDARG;
+ *aNRelations = 0;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ MOZ_ASSERT(!acc->IsProxy());
+
+ 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)++;
+ }
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_relation(long aRelationIndex,
+ IAccessibleRelation** aRelation)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aRelation || aRelationIndex < 0)
+ return E_INVALIDARG;
+ *aRelation = nullptr;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ MOZ_ASSERT(!acc->IsProxy());
+
+ long relIdx = 0;
+ 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);
+ RefPtr<ia2AccessibleRelation> ia2Relation =
+ new ia2AccessibleRelation(relationType, &rel);
+ if (ia2Relation->HasTargets()) {
+ if (relIdx == aRelationIndex) {
+ ia2Relation.forget(aRelation);
+ return S_OK;
+ }
+
+ relIdx++;
+ }
+ }
+
+ return E_INVALIDARG;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_relations(long aMaxRelations,
+ IAccessibleRelation** aRelation,
+ long *aNRelations)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aRelation || !aNRelations || aMaxRelations <= 0)
+ return E_INVALIDARG;
+ *aNRelations = 0;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ MOZ_ASSERT(!acc->IsProxy());
+
+ for (uint32_t idx = 0; idx < ArrayLength(sRelationTypePairs) &&
+ *aNRelations < aMaxRelations; idx++) {
+ if (sRelationTypePairs[idx].second == IA2_RELATION_NULL)
+ continue;
+
+ RelationType relationType = sRelationTypePairs[idx].first;
+ Relation rel = acc->RelationByType(relationType);
+ RefPtr<ia2AccessibleRelation> ia2Rel =
+ new ia2AccessibleRelation(relationType, &rel);
+ if (ia2Rel->HasTargets()) {
+ ia2Rel.forget(aRelation + (*aNRelations));
+ (*aNRelations)++;
+ }
+ }
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::role(long* aRole)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aRole)
+ return E_INVALIDARG;
+ *aRole = 0;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+#define ROLE(_geckoRole, stringRole, atkRole, macRole, \
+ msaaRole, ia2Role, nameRule) \
+ case roles::_geckoRole: \
+ *aRole = ia2Role; \
+ break;
+
+ a11y::role geckoRole;
+ MOZ_ASSERT(!acc->IsProxy());
+ geckoRole = acc->Role();
+ switch (geckoRole) {
+#include "RoleMap.h"
+ default:
+ MOZ_CRASH("Unknown role.");
+ }
+
+#undef ROLE
+
+ // Special case, if there is a ROLE_ROW inside of a ROLE_TREE_TABLE, then call
+ // the IA2 role a ROLE_OUTLINEITEM.
+ MOZ_ASSERT(!acc->IsProxy());
+ if (geckoRole == roles::ROW) {
+ Accessible* xpParent = acc->Parent();
+ if (xpParent && xpParent->Role() == roles::TREE_TABLE)
+ *aRole = ROLE_SYSTEM_OUTLINEITEM;
+ }
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::scrollTo(enum IA2ScrollType aScrollType)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ MOZ_ASSERT(!acc->IsProxy());
+ nsCoreUtils::ScrollTo(acc->Document()->PresShell(), acc->GetContent(),
+ aScrollType);
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::scrollToPoint(enum IA2CoordinateType aCoordType,
+ long aX, long aY)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
+ nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
+ nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
+
+ MOZ_ASSERT(!acc->IsProxy());
+ acc->ScrollToPoint(geckoCoordType, aX, aY);
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_groupPosition(long* aGroupLevel,
+ long* aSimilarItemsInGroup,
+ long* aPositionInGroup)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aGroupLevel || !aSimilarItemsInGroup || !aPositionInGroup)
+ return E_INVALIDARG;
+
+ *aGroupLevel = 0;
+ *aSimilarItemsInGroup = 0;
+ *aPositionInGroup = 0;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ GroupPos groupPos = acc->GroupPosition();
+
+ // Group information for accessibles having level only (like html headings
+ // elements) isn't exposed by this method. AT should look for 'level' object
+ // attribute.
+ if (!groupPos.setSize && !groupPos.posInSet)
+ return S_FALSE;
+
+ *aGroupLevel = groupPos.level;
+ *aSimilarItemsInGroup = groupPos.setSize;
+ *aPositionInGroup = groupPos.posInSet;
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_states(AccessibleStates* aStates)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aStates)
+ return E_INVALIDARG;
+ *aStates = 0;
+
+ // XXX: bug 344674 should come with better approach that we have here.
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct()) {
+ *aStates = IA2_STATE_DEFUNCT;
+ return S_OK;
+ }
+
+ uint64_t state;
+ MOZ_ASSERT(!acc->IsProxy());
+ state = acc->State();
+
+ if (state & states::INVALID)
+ *aStates |= IA2_STATE_INVALID_ENTRY;
+ if (state & states::REQUIRED)
+ *aStates |= IA2_STATE_REQUIRED;
+
+ // The following IA2 states are not supported by Gecko
+ // IA2_STATE_ARMED
+ // IA2_STATE_MANAGES_DESCENDANTS
+ // IA2_STATE_ICONIFIED
+ // IA2_STATE_INVALID // This is not a state, it is the absence of a state
+
+ if (state & states::ACTIVE)
+ *aStates |= IA2_STATE_ACTIVE;
+ if (state & states::DEFUNCT)
+ *aStates |= IA2_STATE_DEFUNCT;
+ if (state & states::EDITABLE)
+ *aStates |= IA2_STATE_EDITABLE;
+ if (state & states::HORIZONTAL)
+ *aStates |= IA2_STATE_HORIZONTAL;
+ if (state & states::MODAL)
+ *aStates |= IA2_STATE_MODAL;
+ if (state & states::MULTI_LINE)
+ *aStates |= IA2_STATE_MULTI_LINE;
+ if (state & states::OPAQUE1)
+ *aStates |= IA2_STATE_OPAQUE;
+ if (state & states::SELECTABLE_TEXT)
+ *aStates |= IA2_STATE_SELECTABLE_TEXT;
+ if (state & states::SINGLE_LINE)
+ *aStates |= IA2_STATE_SINGLE_LINE;
+ if (state & states::STALE)
+ *aStates |= IA2_STATE_STALE;
+ if (state & states::SUPPORTS_AUTOCOMPLETION)
+ *aStates |= IA2_STATE_SUPPORTS_AUTOCOMPLETION;
+ if (state & states::TRANSIENT)
+ *aStates |= IA2_STATE_TRANSIENT;
+ if (state & states::VERTICAL)
+ *aStates |= IA2_STATE_VERTICAL;
+ if (state & states::CHECKED)
+ *aStates |= IA2_STATE_CHECKABLE;
+ if (state & states::PINNED)
+ *aStates |= IA2_STATE_PINNED;
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_extendedRole(BSTR* aExtendedRole)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aExtendedRole)
+ return E_INVALIDARG;
+
+ *aExtendedRole = nullptr;
+ return E_NOTIMPL;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_localizedExtendedRole(BSTR* aLocalizedExtendedRole)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aLocalizedExtendedRole)
+ return E_INVALIDARG;
+
+ *aLocalizedExtendedRole = nullptr;
+ return E_NOTIMPL;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_nExtendedStates(long* aNExtendedStates)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aNExtendedStates)
+ return E_INVALIDARG;
+
+ *aNExtendedStates = 0;
+ return E_NOTIMPL;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_extendedStates(long aMaxExtendedStates,
+ BSTR** aExtendedStates,
+ long* aNExtendedStates)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aExtendedStates || !aNExtendedStates)
+ return E_INVALIDARG;
+
+ *aExtendedStates = nullptr;
+ *aNExtendedStates = 0;
+ return E_NOTIMPL;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_localizedExtendedStates(long aMaxLocalizedExtendedStates,
+ BSTR** aLocalizedExtendedStates,
+ long* aNLocalizedExtendedStates)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aLocalizedExtendedStates || !aNLocalizedExtendedStates)
+ return E_INVALIDARG;
+
+ *aLocalizedExtendedStates = nullptr;
+ *aNLocalizedExtendedStates = 0;
+ return E_NOTIMPL;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_uniqueID(long* aUniqueID)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aUniqueID)
+ return E_INVALIDARG;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ *aUniqueID = AccessibleWrap::GetChildIDFor(acc);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_windowHandle(HWND* aWindowHandle)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aWindowHandle)
+ return E_INVALIDARG;
+ *aWindowHandle = 0;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ *aWindowHandle = AccessibleWrap::GetHWNDFor(acc);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_indexInParent(long* aIndexInParent)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aIndexInParent)
+ return E_INVALIDARG;
+ *aIndexInParent = -1;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ MOZ_ASSERT(!acc->IsProxy());
+ *aIndexInParent = acc->IndexInParent();
+
+ if (*aIndexInParent == -1)
+ return S_FALSE;
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_locale(IA2Locale* aLocale)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aLocale)
+ return E_INVALIDARG;
+
+ // Language codes consist of a primary code and a possibly empty series of
+ // subcodes: language-code = primary-code ( "-" subcode )*
+ // Two-letter primary codes are reserved for [ISO639] language abbreviations.
+ // Any two-letter subcode is understood to be a [ISO3166] country code.
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ nsAutoString lang;
+ acc->Language(lang);
+
+ // If primary code consists from two letters then expose it as language.
+ int32_t offset = lang.FindChar('-', 0);
+ if (offset == -1) {
+ if (lang.Length() == 2) {
+ aLocale->language = ::SysAllocString(lang.get());
+ return S_OK;
+ }
+ } else if (offset == 2) {
+ aLocale->language = ::SysAllocStringLen(lang.get(), 2);
+
+ // If the first subcode consists from two letters then expose it as
+ // country.
+ offset = lang.FindChar('-', 3);
+ if (offset == -1) {
+ if (lang.Length() == 5) {
+ aLocale->country = ::SysAllocString(lang.get() + 3);
+ return S_OK;
+ }
+ } else if (offset == 5) {
+ aLocale->country = ::SysAllocStringLen(lang.get() + 3, 2);
+ }
+ }
+
+ // Expose as a string if primary code or subcode cannot point to language or
+ // country abbreviations or if there are more than one subcode.
+ aLocale->variant = ::SysAllocString(lang.get());
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_attributes(BSTR* aAttributes)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aAttributes)
+ return E_INVALIDARG;
+ *aAttributes = nullptr;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ // The format is name:value;name:value; with \ for escaping these
+ // characters ":;=,\".
+ if (!acc->IsProxy()) {
+ nsCOMPtr<nsIPersistentProperties> attributes = acc->Attributes();
+ return ConvertToIA2Attributes(attributes, aAttributes);
+ }
+
+ MOZ_ASSERT(!acc->IsProxy());
+ return E_UNEXPECTED;
+
+ A11Y_TRYBLOCK_END
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// IAccessible2_2
+
+STDMETHODIMP
+ia2Accessible::get_attribute(BSTR name, VARIANT* aAttribute)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aAttribute)
+ return E_INVALIDARG;
+
+ return E_NOTIMPL;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_accessibleWithCaret(IUnknown** aAccessible,
+ long* aCaretOffset)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aAccessible || !aCaretOffset)
+ return E_INVALIDARG;
+
+ *aAccessible = nullptr;
+ *aCaretOffset = -1;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ int32_t caretOffset = -1;
+ Accessible* accWithCaret = SelectionMgr()->AccessibleWithCaret(&caretOffset);
+ if (acc->Document() != accWithCaret->Document())
+ return S_FALSE;
+
+ Accessible* child = accWithCaret;
+ while (!child->IsDoc() && child != acc)
+ child = child->Parent();
+
+ if (child != acc)
+ return S_FALSE;
+
+ *aAccessible = static_cast<IAccessible2*>(
+ static_cast<AccessibleWrap*>(accWithCaret));
+ (*aAccessible)->AddRef();
+ *aCaretOffset = caretOffset;
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_relationTargetsOfType(BSTR aType,
+ long aMaxTargets,
+ IUnknown*** aTargets,
+ long* aNTargets)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aTargets || !aNTargets || aMaxTargets < 0)
+ return E_INVALIDARG;
+ *aNTargets = 0;
+
+ Maybe<RelationType> relationType;
+ for (uint32_t idx = 0; idx < ArrayLength(sRelationTypePairs); idx++) {
+ if (wcscmp(aType, sRelationTypePairs[idx].second) == 0) {
+ relationType.emplace(sRelationTypePairs[idx].first);
+ break;
+ }
+ }
+ if (!relationType)
+ return E_INVALIDARG;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ nsTArray<Accessible*> targets;
+ MOZ_ASSERT(!acc->IsProxy());
+ Relation rel = acc->RelationByType(*relationType);
+ Accessible* target = nullptr;
+ while ((target = rel.Next()) &&
+ static_cast<long>(targets.Length()) <= aMaxTargets) {
+ targets.AppendElement(target);
+ }
+
+ *aNTargets = targets.Length();
+ *aTargets = static_cast<IUnknown**>(
+ ::CoTaskMemAlloc(sizeof(IUnknown*) * *aNTargets));
+ if (!*aTargets)
+ return E_OUTOFMEMORY;
+
+ for (int32_t i = 0; i < *aNTargets; i++) {
+ AccessibleWrap* target= static_cast<AccessibleWrap*>(targets[i]);
+ (*aTargets)[i] = static_cast<IAccessible2*>(target);
+ (*aTargets)[i]->AddRef();
+ }
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2Accessible::get_selectionRanges(IA2Range** aRanges,
+ long *aNRanges)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aRanges || !aNRanges)
+ return E_INVALIDARG;
+
+ *aNRanges = 0;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ AutoTArray<TextRange, 1> ranges;
+ acc->Document()->SelectionRanges(&ranges);
+ uint32_t len = ranges.Length();
+ for (uint32_t idx = 0; idx < len; idx++) {
+ if (!ranges[idx].Crop(acc)) {
+ ranges.RemoveElementAt(idx);
+ }
+ }
+
+ *aNRanges = ranges.Length();
+ *aRanges = static_cast<IA2Range*>(
+ ::CoTaskMemAlloc(sizeof(IA2Range) * *aNRanges));
+ if (!*aRanges)
+ return E_OUTOFMEMORY;
+
+ for (uint32_t idx = 0; idx < static_cast<uint32_t>(*aNRanges); idx++) {
+ AccessibleWrap* anchor =
+ static_cast<AccessibleWrap*>(ranges[idx].StartContainer());
+ (*aRanges)[idx].anchor = static_cast<IAccessible2*>(anchor);
+ anchor->AddRef();
+
+ (*aRanges)[idx].anchorOffset = ranges[idx].StartOffset();
+
+ AccessibleWrap* active =
+ static_cast<AccessibleWrap*>(ranges[idx].EndContainer());
+ (*aRanges)[idx].active = static_cast<IAccessible2*>(active);
+ active->AddRef();
+
+ (*aRanges)[idx].activeOffset = ranges[idx].EndOffset();
+ }
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Helpers
+
+template<typename String>
+static inline void
+EscapeAttributeChars(String& aStr)
+{
+ int32_t offset = 0;
+ static const char kCharsToEscape[] = ":;=,\\";
+ while ((offset = aStr.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
+ aStr.Insert('\\', offset);
+ offset += 2;
+ }
+}
+
+HRESULT
+ia2Accessible::ConvertToIA2Attributes(nsTArray<Attribute>* aAttributes,
+ BSTR* aIA2Attributes)
+{
+ nsString attrStr;
+ size_t attrCount = aAttributes->Length();
+ for (size_t i = 0; i < attrCount; i++) {
+ EscapeAttributeChars(aAttributes->ElementAt(i).Name());
+ EscapeAttributeChars(aAttributes->ElementAt(i).Value());
+ AppendUTF8toUTF16(aAttributes->ElementAt(i).Name(), attrStr);
+ attrStr.Append(':');
+ attrStr.Append(aAttributes->ElementAt(i).Value());
+ attrStr.Append(';');
+ }
+
+ if (attrStr.IsEmpty())
+ return S_FALSE;
+
+ *aIA2Attributes = ::SysAllocStringLen(attrStr.get(), attrStr.Length());
+ return *aIA2Attributes ? S_OK : E_OUTOFMEMORY;
+}
+
+HRESULT
+ia2Accessible::ConvertToIA2Attributes(nsIPersistentProperties* aAttributes,
+ BSTR* aIA2Attributes)
+{
+ *aIA2Attributes = nullptr;
+
+ // The format is name:value;name:value; with \ for escaping these
+ // characters ":;=,\".
+
+ if (!aAttributes)
+ return S_FALSE;
+
+ nsCOMPtr<nsISimpleEnumerator> propEnum;
+ aAttributes->Enumerate(getter_AddRefs(propEnum));
+ if (!propEnum)
+ return E_FAIL;
+
+ nsAutoString strAttrs;
+
+ bool hasMore = false;
+ while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
+ nsCOMPtr<nsISupports> propSupports;
+ propEnum->GetNext(getter_AddRefs(propSupports));
+
+ nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(propSupports));
+ if (!propElem)
+ return E_FAIL;
+
+ nsAutoCString name;
+ if (NS_FAILED(propElem->GetKey(name)))
+ return E_FAIL;
+
+ EscapeAttributeChars(name);
+
+ nsAutoString value;
+ if (NS_FAILED(propElem->GetValue(value)))
+ return E_FAIL;
+
+ EscapeAttributeChars(value);
+
+ AppendUTF8toUTF16(name, strAttrs);
+ strAttrs.Append(':');
+ strAttrs.Append(value);
+ strAttrs.Append(';');
+ }
+
+ if (strAttrs.IsEmpty())
+ return S_FALSE;
+
+ *aIA2Attributes = ::SysAllocStringLen(strAttrs.get(), strAttrs.Length());
+ return *aIA2Attributes ? S_OK : E_OUTOFMEMORY;
+}
diff --git a/accessible/windows/ia2/ia2Accessible.h b/accessible/windows/ia2/ia2Accessible.h
new file mode 100644
index 000000000..98ca4339b
--- /dev/null
+++ b/accessible/windows/ia2/ia2Accessible.h
@@ -0,0 +1,122 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_ia2Accessible_h_
+#define mozilla_a11y_ia2Accessible_h_
+
+#include "nsISupports.h"
+
+#include "Accessible2_3.h"
+
+namespace mozilla {
+namespace a11y {
+class Attribute;
+
+class ia2Accessible : public IAccessible2_3
+{
+public:
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID, void**);
+
+ // IAccessible2
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nRelations(
+ /* [retval][out] */ long* nRelations);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_relation(
+ /* [in] */ long relationIndex,
+ /* [retval][out] */ IAccessibleRelation** relation);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_relations(
+ /* [in] */ long maxRelations,
+ /* [length_is][size_is][out] */ IAccessibleRelation** relation,
+ /* [retval][out] */ long* nRelations);
+
+ virtual HRESULT STDMETHODCALLTYPE role(
+ /* [retval][out] */ long* role);
+
+ virtual HRESULT STDMETHODCALLTYPE scrollTo(
+ /* [in] */ enum IA2ScrollType scrollType);
+
+ virtual HRESULT STDMETHODCALLTYPE scrollToPoint(
+ /* [in] */ enum IA2CoordinateType coordinateType,
+ /* [in] */ long x,
+ /* [in] */ long y);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_groupPosition(
+ /* [out] */ long* groupLevel,
+ /* [out] */ long* similarItemsInGroup,
+ /* [retval][out] */ long* positionInGroup);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_states(
+ /* [retval][out] */ AccessibleStates* states);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_extendedRole(
+ /* [retval][out] */ BSTR* extendedRole);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_localizedExtendedRole(
+ /* [retval][out] */ BSTR* localizedExtendedRole);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nExtendedStates(
+ /* [retval][out] */ long* nExtendedStates);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_extendedStates(
+ /* [in] */ long maxExtendedStates,
+ /* [length_is][length_is][size_is][size_is][out] */ BSTR** extendedStates,
+ /* [retval][out] */ long* nExtendedStates);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_localizedExtendedStates(
+ /* [in] */ long maxLocalizedExtendedStates,
+ /* [length_is][length_is][size_is][size_is][out] */ BSTR** localizedExtendedStates,
+ /* [retval][out] */ long* nLocalizedExtendedStates);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_uniqueID(
+ /* [retval][out] */ long* uniqueID);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_windowHandle(
+ /* [retval][out] */ HWND* windowHandle);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_indexInParent(
+ /* [retval][out] */ long* indexInParent);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_locale(
+ /* [retval][out] */ IA2Locale* locale);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_attributes(
+ /* [retval][out] */ BSTR* attributes);
+
+ // IAccessible2_2
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_attribute(
+ /* [in] */ BSTR name,
+ /* [out, retval] */ VARIANT* attribute);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_accessibleWithCaret(
+ /* [out] */ IUnknown** accessible,
+ /* [out, retval] */ long* caretOffset);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_relationTargetsOfType(
+ /* [in] */ BSTR type,
+ /* [in] */ long maxTargets,
+ /* [out, size_is(,*nTargets)] */ IUnknown*** targets,
+ /* [out, retval] */ long* nTargets
+ );
+
+ // IAccessible2_3
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_selectionRanges(
+ /* [out, size_is(,*nRanges)] */ IA2Range** ranges,
+ /* [out, retval] */ long *nRanges);
+
+ // Helper method
+ static HRESULT ConvertToIA2Attributes(nsIPersistentProperties* aAttributes,
+ BSTR* aIA2Attributes);
+ static HRESULT ConvertToIA2Attributes(nsTArray<Attribute>* aAttributes,
+ BSTR* aIA2Attributes);
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/windows/ia2/ia2AccessibleAction.cpp b/accessible/windows/ia2/ia2AccessibleAction.cpp
new file mode 100644
index 000000000..0710b753f
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleAction.cpp
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#include "ia2AccessibleAction.h"
+
+#include "AccessibleAction_i.c"
+
+#include "AccessibleWrap.h"
+#include "IUnknownImpl.h"
+
+using namespace mozilla::a11y;
+
+// IUnknown
+
+STDMETHODIMP
+ia2AccessibleAction::QueryInterface(REFIID iid, void** ppv)
+{
+ if (!ppv)
+ return E_INVALIDARG;
+
+ *ppv = nullptr;
+
+ if (IID_IAccessibleAction == iid &&
+ !static_cast<AccessibleWrap*>(this)->IsProxy()) {
+ *ppv = static_cast<IAccessibleAction*>(this);
+ (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+// IAccessibleAction
+
+STDMETHODIMP
+ia2AccessibleAction::nActions(long* aActionCount)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aActionCount)
+ return E_INVALIDARG;
+
+ *aActionCount = 0;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ *aActionCount = acc->ActionCount();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleAction::doAction(long aActionIndex)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ uint8_t index = static_cast<uint8_t>(aActionIndex);
+ return acc->DoAction(index) ? S_OK : E_INVALIDARG;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleAction::get_description(long aActionIndex, BSTR *aDescription)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aDescription)
+ return E_INVALIDARG;
+ *aDescription = nullptr;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ nsAutoString description;
+ uint8_t index = static_cast<uint8_t>(aActionIndex);
+ acc->ActionDescriptionAt(index, description);
+ if (description.IsEmpty())
+ return S_FALSE;
+
+ *aDescription = ::SysAllocStringLen(description.get(),
+ description.Length());
+ return *aDescription ? S_OK : E_OUTOFMEMORY;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleAction::get_keyBinding(long aActionIndex, long aNumMaxBinding,
+ BSTR **aKeyBinding,
+ long *aNumBinding)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aKeyBinding)
+ return E_INVALIDARG;
+ *aKeyBinding = nullptr;
+
+ if (!aNumBinding)
+ return E_INVALIDARG;
+ *aNumBinding = 0;
+
+ if (aActionIndex != 0 || aNumMaxBinding < 1)
+ return E_INVALIDARG;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ // Expose keyboard shortcut if it's not exposed via MSAA keyboard shortcut.
+ KeyBinding keyBinding = acc->AccessKey();
+ if (keyBinding.IsEmpty())
+ return S_FALSE;
+
+ keyBinding = acc->KeyboardShortcut();
+ if (keyBinding.IsEmpty())
+ return S_FALSE;
+
+ nsAutoString keyStr;
+ keyBinding.ToString(keyStr);
+
+ *aKeyBinding = static_cast<BSTR*>(::CoTaskMemAlloc(sizeof(BSTR*)));
+ if (!*aKeyBinding)
+ return E_OUTOFMEMORY;
+
+ *(aKeyBinding[0]) = ::SysAllocStringLen(keyStr.get(), keyStr.Length());
+ if (!*(aKeyBinding[0])) {
+ ::CoTaskMemFree(*aKeyBinding);
+ return E_OUTOFMEMORY;
+ }
+
+ *aNumBinding = 1;
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleAction::get_name(long aActionIndex, BSTR *aName)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aName)
+ return E_INVALIDARG;
+
+ *aName = nullptr;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ nsAutoString name;
+ uint8_t index = static_cast<uint8_t>(aActionIndex);
+ acc->ActionNameAt(index, name);
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+
+ *aName = ::SysAllocStringLen(name.get(), name.Length());
+ return *aName ? S_OK : E_OUTOFMEMORY;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleAction::get_localizedName(long aActionIndex, BSTR *aLocalizedName)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aLocalizedName)
+ return E_INVALIDARG;
+
+ *aLocalizedName = nullptr;
+ return E_NOTIMPL;
+
+ A11Y_TRYBLOCK_END
+}
diff --git a/accessible/windows/ia2/ia2AccessibleAction.h b/accessible/windows/ia2/ia2AccessibleAction.h
new file mode 100644
index 000000000..6c978ff16
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleAction.h
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#ifndef _ACCESSIBLE_ACTION_H
+#define _ACCESSIBLE_ACTION_H
+
+#include "nsISupports.h"
+
+#include "AccessibleAction.h"
+
+namespace mozilla {
+namespace a11y {
+
+class ia2AccessibleAction: public IAccessibleAction
+{
+public:
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID, void**);
+
+ // IAccessibleAction
+ virtual HRESULT STDMETHODCALLTYPE nActions(
+ /* [retval][out] */ long *nActions);
+
+ virtual HRESULT STDMETHODCALLTYPE doAction(
+ /* [in] */ long actionIndex);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_description(
+ /* [in] */ long actionIndex,
+ /* [retval][out] */ BSTR *description);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_keyBinding(
+ /* [in] */ long actionIndex,
+ /* [in] */ long nMaxBinding,
+ /* [length_is][length_is][size_is][size_is][out] */ BSTR **keyBinding,
+ /* [retval][out] */ long *nBinding);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_name(
+ /* [in] */ long actionIndex,
+ /* [retval][out] */ BSTR *name);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_localizedName(
+ /* [in] */ long actionIndex,
+ /* [retval][out] */ BSTR *localizedName);
+
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#define FORWARD_IACCESSIBLEACTION(Class) \
+virtual HRESULT STDMETHODCALLTYPE nActions(long *nActions) \
+{ \
+ return Class::nActions(nActions); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE doAction(long actionIndex) \
+{ \
+ return Class::doAction(actionIndex); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_description(long actionIndex, \
+ BSTR *description) \
+{ \
+ return Class::get_description(actionIndex, description); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_keyBinding(long actionIndex, \
+ long nMaxBinding, \
+ BSTR **keyBinding, \
+ long *nBinding) \
+{ \
+ return Class::get_keyBinding(actionIndex, nMaxBinding, keyBinding, nBinding);\
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_name(long actionIndex, BSTR *name) \
+{ \
+ return Class::get_name(actionIndex, name); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_localizedName(long actionIndex, \
+ BSTR *localizedName) \
+{ \
+ return Class::get_localizedName(actionIndex, localizedName); \
+} \
+ \
+
+#endif
+
diff --git a/accessible/windows/ia2/ia2AccessibleComponent.cpp b/accessible/windows/ia2/ia2AccessibleComponent.cpp
new file mode 100644
index 000000000..f32c09d1e
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleComponent.cpp
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#include "ia2AccessibleComponent.h"
+
+#include "AccessibleComponent_i.c"
+
+#include "AccessibleWrap.h"
+#include "States.h"
+#include "IUnknownImpl.h"
+
+#include "nsIFrame.h"
+
+using namespace mozilla::a11y;
+
+// IUnknown
+
+STDMETHODIMP
+ia2AccessibleComponent::QueryInterface(REFIID iid, void** ppv)
+{
+ if (!ppv)
+ return E_INVALIDARG;
+
+ *ppv = nullptr;
+
+ if (IID_IAccessibleComponent == iid) {
+ *ppv = static_cast<IAccessibleComponent*>(this);
+ (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+// IAccessibleComponent
+
+STDMETHODIMP
+ia2AccessibleComponent::get_locationInParent(long* aX, long* aY)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aX || !aY)
+ return E_INVALIDARG;
+
+ *aX = 0;
+ *aY = 0;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ // If the object is not on any screen the returned position is (0,0).
+ uint64_t state = acc->State();
+ if (state & states::INVISIBLE)
+ return S_OK;
+
+ nsIntRect rect = acc->Bounds();
+
+ // The coordinates of the returned position are relative to this object's
+ // parent or relative to the screen on which this object is rendered if it
+ // has no parent.
+ if (!acc->Parent()) {
+ *aX = rect.x;
+ *aY = rect.y;
+ return S_OK;
+ }
+
+ // The coordinates of the bounding box are given relative to the parent's
+ // coordinate system.
+ nsIntRect parentRect = acc->Parent()->Bounds();
+ *aX = rect.x - parentRect.x;
+ *aY = rect.y - parentRect.y;
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleComponent::get_foreground(IA2Color* aForeground)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aForeground)
+ return E_INVALIDARG;
+
+ *aForeground = 0;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ nsIFrame* frame = acc->GetFrame();
+ if (frame)
+ *aForeground = frame->StyleColor()->mColor;
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleComponent::get_background(IA2Color* aBackground)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aBackground)
+ return E_INVALIDARG;
+
+ *aBackground = 0;
+
+ AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ nsIFrame* frame = acc->GetFrame();
+ if (frame)
+ *aBackground = frame->StyleBackground()->mBackgroundColor;
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
diff --git a/accessible/windows/ia2/ia2AccessibleComponent.h b/accessible/windows/ia2/ia2AccessibleComponent.h
new file mode 100644
index 000000000..c14d7a113
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleComponent.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#ifndef IA2_ACCESSIBLE_COMPONENT_H_
+#define IA2_ACCESSIBLE_COMPONENT_H_
+
+#include "AccessibleComponent.h"
+
+namespace mozilla {
+namespace a11y {
+
+class ia2AccessibleComponent : public IAccessibleComponent
+{
+public:
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID, void**);
+
+ // IAccessibleComponent
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_locationInParent(
+ /* [out] */ long *x,
+ /* [retval][out] */ long *y);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_foreground(
+ /* [retval][out] */ IA2Color *foreground);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_background(
+ /* [retval][out] */ IA2Color *background);
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/windows/ia2/ia2AccessibleEditableText.cpp b/accessible/windows/ia2/ia2AccessibleEditableText.cpp
new file mode 100644
index 000000000..361d6a130
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleEditableText.cpp
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#include "ia2AccessibleEditableText.h"
+
+#include "AccessibleEditableText_i.c"
+#include "HyperTextAccessible-inl.h"
+#include "HyperTextAccessibleWrap.h"
+#include "ProxyWrappers.h"
+
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+using namespace mozilla::a11y;
+
+// IAccessibleEditableText
+
+STDMETHODIMP
+ia2AccessibleEditableText::copyText(long aStartOffset, long aEndOffset)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!textAcc->IsValidRange(aStartOffset, aEndOffset))
+ return E_INVALIDARG;
+
+ textAcc->CopyText(aStartOffset, aEndOffset);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleEditableText::deleteText(long aStartOffset, long aEndOffset)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!textAcc->IsValidRange(aStartOffset, aEndOffset))
+ return E_INVALIDARG;
+
+ textAcc->DeleteText(aStartOffset, aEndOffset);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleEditableText::insertText(long aOffset, BSTR *aText)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ uint32_t length = ::SysStringLen(*aText);
+ nsAutoString text(*aText, length);
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!textAcc->IsValidOffset(aOffset))
+ return E_INVALIDARG;
+
+ textAcc->InsertText(text, aOffset);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleEditableText::cutText(long aStartOffset, long aEndOffset)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!textAcc->IsValidRange(aStartOffset, aEndOffset))
+ return E_INVALIDARG;
+
+ textAcc->CutText(aStartOffset, aEndOffset);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleEditableText::pasteText(long aOffset)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!textAcc->IsValidOffset(aOffset))
+ return E_INVALIDARG;
+
+ textAcc->PasteText(aOffset);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleEditableText::replaceText(long aStartOffset, long aEndOffset,
+ BSTR *aText)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!textAcc->IsValidRange(aStartOffset, aEndOffset))
+ return E_INVALIDARG;
+
+ textAcc->DeleteText(aStartOffset, aEndOffset);
+
+ uint32_t length = ::SysStringLen(*aText);
+ nsAutoString text(*aText, length);
+ textAcc->InsertText(text, aStartOffset);
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleEditableText::setAttributes(long aStartOffset, long aEndOffset,
+ BSTR *aAttributes)
+{
+ return E_NOTIMPL;
+}
diff --git a/accessible/windows/ia2/ia2AccessibleEditableText.h b/accessible/windows/ia2/ia2AccessibleEditableText.h
new file mode 100644
index 000000000..a1501ca51
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleEditableText.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#ifndef _ACCESSIBLE_EDITABLETEXT_H
+#define _ACCESSIBLE_EDITABLETEXT_H
+
+#include "nsISupports.h"
+
+#include "AccessibleEditableText.h"
+
+namespace mozilla {
+namespace a11y {
+
+class ia2AccessibleEditableText: public IAccessibleEditableText
+{
+public:
+
+ // IAccessibleEditableText
+ virtual HRESULT STDMETHODCALLTYPE copyText(
+ /* [in] */ long startOffset,
+ /* [in] */ long endOffset);
+
+ virtual HRESULT STDMETHODCALLTYPE deleteText(
+ /* [in] */ long startOffset,
+ /* [in] */ long endOffset);
+
+ virtual HRESULT STDMETHODCALLTYPE insertText(
+ /* [in] */ long offset,
+ /* [in] */ BSTR *text);
+
+ virtual HRESULT STDMETHODCALLTYPE cutText(
+ /* [in] */ long startOffset,
+ /* [in] */ long endOffset);
+
+ virtual HRESULT STDMETHODCALLTYPE pasteText(
+ /* [in] */ long offset);
+
+ virtual HRESULT STDMETHODCALLTYPE replaceText(
+ /* [in] */ long startOffset,
+ /* [in] */ long endOffset,
+ /* [in] */ BSTR *text);
+
+ virtual HRESULT STDMETHODCALLTYPE setAttributes(
+ /* [in] */ long startOffset,
+ /* [in] */ long endOffset,
+ /* [in] */ BSTR *attributes);
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/windows/ia2/ia2AccessibleHyperlink.cpp b/accessible/windows/ia2/ia2AccessibleHyperlink.cpp
new file mode 100644
index 000000000..c6d564103
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleHyperlink.cpp
@@ -0,0 +1,205 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#include "Accessible2.h"
+#include "AccessibleHyperlink.h"
+#include "AccessibleHyperlink_i.c"
+
+#include "AccessibleWrap.h"
+#include "IUnknownImpl.h"
+#include "nsIURI.h"
+
+using namespace mozilla::a11y;
+
+// IUnknown
+
+STDMETHODIMP
+ia2AccessibleHyperlink::QueryInterface(REFIID iid, void** ppv)
+{
+ if (!ppv)
+ return E_INVALIDARG;
+
+ *ppv = nullptr;
+
+ if (IID_IAccessibleHyperlink == iid) {
+ auto accWrap = static_cast<AccessibleWrap*>(this);
+ if (accWrap->IsProxy() ?
+ !(accWrap->ProxyInterfaces() & Interfaces::HYPERLINK) :
+ !accWrap->IsLink())
+ return E_NOINTERFACE;
+
+ *ppv = static_cast<IAccessibleHyperlink*>(this);
+ (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
+ return S_OK;
+ }
+
+ return ia2AccessibleAction::QueryInterface(iid, ppv);
+}
+
+// IAccessibleHyperlink
+
+STDMETHODIMP
+ia2AccessibleHyperlink::get_anchor(long aIndex, VARIANT* aAnchor)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aAnchor)
+ return E_INVALIDARG;
+
+ VariantInit(aAnchor);
+
+ Accessible* thisObj = static_cast<AccessibleWrap*>(this);
+ MOZ_ASSERT(!thisObj->IsProxy());
+
+ if (thisObj->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aIndex < 0 || aIndex >= static_cast<long>(thisObj->AnchorCount()))
+ return E_INVALIDARG;
+
+ if (!thisObj->IsLink())
+ return S_FALSE;
+
+ AccessibleWrap* anchor =
+ static_cast<AccessibleWrap*>(thisObj->AnchorAt(aIndex));
+ if (!anchor)
+ return S_FALSE;
+
+ void* instancePtr = nullptr;
+ HRESULT result = anchor->QueryInterface(IID_IUnknown, &instancePtr);
+ if (FAILED(result))
+ return result;
+
+ aAnchor->punkVal = static_cast<IUnknown*>(instancePtr);
+ aAnchor->vt = VT_UNKNOWN;
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleHyperlink::get_anchorTarget(long aIndex, VARIANT* aAnchorTarget)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aAnchorTarget) {
+ return E_INVALIDARG;
+ }
+
+ VariantInit(aAnchorTarget);
+
+ Accessible* thisObj = static_cast<AccessibleWrap*>(this);
+ nsAutoCString uriStr;
+ MOZ_ASSERT(!thisObj->IsProxy());
+ if (thisObj->IsDefunct()) {
+ return CO_E_OBJNOTCONNECTED;
+ }
+
+ if (aIndex < 0 || aIndex >= static_cast<long>(thisObj->AnchorCount())) {
+ return E_INVALIDARG;
+ }
+
+ if (!thisObj->IsLink()) {
+ return S_FALSE;
+ }
+
+ nsCOMPtr<nsIURI> uri = thisObj->AnchorURIAt(aIndex);
+ if (!uri) {
+ return S_FALSE;
+ }
+
+ nsresult rv = uri->GetSpec(uriStr);
+ if (NS_FAILED(rv)) {
+ return GetHRESULT(rv);
+ }
+
+ nsAutoString stringURI;
+ AppendUTF8toUTF16(uriStr, stringURI);
+
+ aAnchorTarget->vt = VT_BSTR;
+ aAnchorTarget->bstrVal = ::SysAllocStringLen(stringURI.get(),
+ stringURI.Length());
+ return aAnchorTarget->bstrVal ? S_OK : E_OUTOFMEMORY;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleHyperlink::get_startIndex(long* aIndex)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aIndex)
+ return E_INVALIDARG;
+
+ *aIndex = 0;
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ Accessible* thisObj = static_cast<AccessibleWrap*>(this);
+ if (thisObj->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!thisObj->IsLink())
+ return S_FALSE;
+
+ *aIndex = thisObj->StartOffset();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleHyperlink::get_endIndex(long* aIndex)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aIndex)
+ return E_INVALIDARG;
+
+ *aIndex = 0;
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ Accessible* thisObj = static_cast<AccessibleWrap*>(this);
+ if (thisObj->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!thisObj->IsLink())
+ return S_FALSE;
+
+ *aIndex = thisObj->EndOffset();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleHyperlink::get_valid(boolean* aValid)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aValid)
+ return E_INVALIDARG;
+
+ *aValid = false;
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ Accessible* thisObj = static_cast<AccessibleWrap*>(this);
+ if (thisObj->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!thisObj->IsLink())
+ return S_FALSE;
+
+ *aValid = thisObj->IsLinkValid();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
diff --git a/accessible/windows/ia2/ia2AccessibleHyperlink.h b/accessible/windows/ia2/ia2AccessibleHyperlink.h
new file mode 100644
index 000000000..dc34f5bc9
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleHyperlink.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#ifndef _ACCESSIBLE_HYPERLINK_H
+#define _ACCESSIBLE_HYPERLINK_H
+
+#include "nsISupports.h"
+
+#include "ia2AccessibleAction.h"
+#include "AccessibleHyperlink.h"
+
+namespace mozilla {
+namespace a11y {
+
+class ia2AccessibleHyperlink : public ia2AccessibleAction,
+ public IAccessibleHyperlink
+{
+public:
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID, void**);
+
+ // IAccessibleAction
+ FORWARD_IACCESSIBLEACTION(ia2AccessibleAction)
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_anchor(
+ /* [in] */ long index,
+ /* [retval][out] */ VARIANT *anchor);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_anchorTarget(
+ /* [in] */ long index,
+ /* [retval][out] */ VARIANT *anchorTarget);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_startIndex(
+ /* [retval][out] */ long *index);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_endIndex(
+ /* [retval][out] */ long *index);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_valid(
+ /* [retval][out] */ boolean *valid);
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/windows/ia2/ia2AccessibleHypertext.cpp b/accessible/windows/ia2/ia2AccessibleHypertext.cpp
new file mode 100644
index 000000000..f4b3bdaf2
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleHypertext.cpp
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#include "ia2AccessibleHypertext.h"
+
+#include "AccessibleHypertext_i.c"
+
+#include "HyperTextAccessibleWrap.h"
+#include "IUnknownImpl.h"
+
+using namespace mozilla::a11y;
+
+// IAccessibleHypertext
+
+STDMETHODIMP
+ia2AccessibleHypertext::get_nHyperlinks(long* aHyperlinkCount)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aHyperlinkCount)
+ return E_INVALIDARG;
+
+ *aHyperlinkCount = 0;
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ HyperTextAccessibleWrap* hyperText = static_cast<HyperTextAccessibleWrap*>(this);
+ if (hyperText->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ *aHyperlinkCount = hyperText->LinkCount();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleHypertext::get_hyperlink(long aLinkIndex,
+ IAccessibleHyperlink** aHyperlink)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aHyperlink)
+ return E_INVALIDARG;
+
+ *aHyperlink = nullptr;
+
+ AccessibleWrap* hyperLink;
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+ HyperTextAccessibleWrap* hyperText = static_cast<HyperTextAccessibleWrap*>(this);
+ if (hyperText->IsDefunct()) {
+ return CO_E_OBJNOTCONNECTED;
+ }
+
+ hyperLink = static_cast<AccessibleWrap*>(hyperText->LinkAt(aLinkIndex));
+
+ if (!hyperLink)
+ return E_FAIL;
+
+ *aHyperlink =
+ static_cast<IAccessibleHyperlink*>(hyperLink);
+ (*aHyperlink)->AddRef();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleHypertext::get_hyperlinkIndex(long aCharIndex, long* aHyperlinkIndex)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aHyperlinkIndex)
+ return E_INVALIDARG;
+
+ *aHyperlinkIndex = 0;
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ HyperTextAccessibleWrap* hyperAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (hyperAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ *aHyperlinkIndex = hyperAcc->LinkIndexAtOffset(aCharIndex);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
diff --git a/accessible/windows/ia2/ia2AccessibleHypertext.h b/accessible/windows/ia2/ia2AccessibleHypertext.h
new file mode 100644
index 000000000..af5c209b4
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleHypertext.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#ifndef _ACCESSIBLE_HYPERTEXT_H
+#define _ACCESSIBLE_HYPERTEXT_H
+
+#include "nsISupports.h"
+
+#include "ia2AccessibleText.h"
+#include "AccessibleHypertext.h"
+
+namespace mozilla {
+namespace a11y {
+
+class ia2AccessibleHypertext : public ia2AccessibleText,
+ public IAccessibleHypertext
+{
+public:
+
+ // IAccessibleText
+ FORWARD_IACCESSIBLETEXT(ia2AccessibleText)
+
+ // IAccessibleHypertext
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nHyperlinks(
+ /* [retval][out] */ long* hyperlinkCount);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_hyperlink(
+ /* [in] */ long index,
+ /* [retval][out] */ IAccessibleHyperlink** hyperlink);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_hyperlinkIndex(
+ /* [in] */ long charIndex,
+ /* [retval][out] */ long* hyperlinkIndex);
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/windows/ia2/ia2AccessibleImage.cpp b/accessible/windows/ia2/ia2AccessibleImage.cpp
new file mode 100644
index 000000000..989fde925
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleImage.cpp
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#include "ia2AccessibleImage.h"
+
+#include "AccessibleImage_i.c"
+
+#include "ImageAccessibleWrap.h"
+#include "IUnknownImpl.h"
+#include "nsIAccessibleTypes.h"
+
+#include "nsString.h"
+#include "nsIURI.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+
+// IUnknown
+
+STDMETHODIMP
+ia2AccessibleImage::QueryInterface(REFIID iid, void** ppv)
+{
+ if (!ppv)
+ return E_INVALIDARG;
+
+ *ppv = nullptr;
+
+ if (IID_IAccessibleImage == iid) {
+ *ppv = static_cast<IAccessibleImage*>(this);
+ (static_cast<IUnknown*>(*ppv))->AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+// IAccessibleImage
+
+STDMETHODIMP
+ia2AccessibleImage::get_description(BSTR* aDescription)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aDescription)
+ return E_INVALIDARG;
+
+ *aDescription = nullptr;
+
+ ImageAccessibleWrap* acc = static_cast<ImageAccessibleWrap*>(this);
+ if (acc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ nsAutoString description;
+ acc->Name(description);
+ if (description.IsEmpty())
+ return S_FALSE;
+
+ *aDescription = ::SysAllocStringLen(description.get(), description.Length());
+ return *aDescription ? S_OK : E_OUTOFMEMORY;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleImage::get_imagePosition(enum IA2CoordinateType aCoordType,
+ long* aX,
+ long* aY)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aX || !aY)
+ return E_INVALIDARG;
+
+ *aX = 0;
+ *aY = 0;
+
+ ImageAccessibleWrap* imageAcc = static_cast<ImageAccessibleWrap*>(this);
+ if (imageAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
+ nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
+ nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
+
+ nsIntPoint pos = imageAcc->Position(geckoCoordType);
+ *aX = pos.x;
+ *aY = pos.y;
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleImage::get_imageSize(long* aHeight, long* aWidth)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aHeight || !aWidth)
+ return E_INVALIDARG;
+
+ *aHeight = 0;
+ *aWidth = 0;
+
+ ImageAccessibleWrap* imageAcc = static_cast<ImageAccessibleWrap*>(this);
+ if (imageAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ nsIntSize size = imageAcc->Size();
+ *aHeight = size.width;
+ *aWidth = size.height;
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
diff --git a/accessible/windows/ia2/ia2AccessibleImage.h b/accessible/windows/ia2/ia2AccessibleImage.h
new file mode 100644
index 000000000..d065cf34c
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleImage.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#ifndef _ACCESSIBLE_IMAGE_H
+#define _ACCESSIBLE_IMAGE_H
+
+#include "AccessibleImage.h"
+
+namespace mozilla {
+namespace a11y {
+
+class ia2AccessibleImage : public IAccessibleImage
+{
+public:
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID, void**);
+
+ // IAccessibleImage
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_description(
+ /* [retval][out] */ BSTR *description);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_imagePosition(
+ /* [in] */ enum IA2CoordinateType coordinateType,
+ /* [out] */ long *x,
+ /* [retval][out] */ long *y);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_imageSize(
+ /* [out] */ long *height,
+ /* [retval][out] */ long *width);
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/windows/ia2/ia2AccessibleRelation.cpp b/accessible/windows/ia2/ia2AccessibleRelation.cpp
new file mode 100644
index 000000000..cc6fd83c8
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleRelation.cpp
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#include "ia2AccessibleRelation.h"
+
+#include "Relation.h"
+#include "nsID.h"
+
+#include "AccessibleRelation_i.c"
+
+using namespace mozilla::a11y;
+
+ia2AccessibleRelation::ia2AccessibleRelation(RelationType aType, Relation* aRel) :
+ mType(aType)
+{
+ Accessible* target = nullptr;
+ while ((target = aRel->Next()))
+ mTargets.AppendElement(target);
+}
+
+// IUnknown
+
+IMPL_IUNKNOWN_QUERY_HEAD(ia2AccessibleRelation)
+ IMPL_IUNKNOWN_QUERY_IFACE(IAccessibleRelation)
+ IMPL_IUNKNOWN_QUERY_IFACE(IUnknown)
+IMPL_IUNKNOWN_QUERY_TAIL
+
+// IAccessibleRelation
+
+STDMETHODIMP
+ia2AccessibleRelation::get_relationType(BSTR* aRelationType)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aRelationType)
+ return E_INVALIDARG;
+
+ *aRelationType = nullptr;
+
+#define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \
+ case RelationType::geckoType: \
+ *aRelationType = ::SysAllocString(ia2Type); \
+ break;
+
+ switch (mType) {
+#include "RelationTypeMap.h"
+ }
+
+ return *aRelationType ? S_OK : E_OUTOFMEMORY;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleRelation::get_localizedRelationType(BSTR *aLocalizedRelationType)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aLocalizedRelationType)
+ return E_INVALIDARG;
+
+ *aLocalizedRelationType = nullptr;
+ return E_NOTIMPL;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleRelation::get_nTargets(long *aNTargets)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aNTargets)
+ return E_INVALIDARG;
+
+ *aNTargets = mTargets.Length();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleRelation::get_target(long aTargetIndex, IUnknown **aTarget)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (aTargetIndex < 0 || (uint32_t)aTargetIndex >= mTargets.Length() || !aTarget)
+ return E_INVALIDARG;
+
+ AccessibleWrap* target =
+ static_cast<AccessibleWrap*>(mTargets[aTargetIndex].get());
+ *aTarget = static_cast<IAccessible*>(target);
+ (*aTarget)->AddRef();
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleRelation::get_targets(long aMaxTargets, IUnknown **aTargets,
+ long *aNTargets)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aNTargets || !aTargets)
+ return E_INVALIDARG;
+
+ *aNTargets = 0;
+ long maxTargets = mTargets.Length();
+ if (maxTargets > aMaxTargets)
+ maxTargets = aMaxTargets;
+
+ for (long idx = 0; idx < maxTargets; idx++)
+ get_target(idx, aTargets + idx);
+
+ *aNTargets = maxTargets;
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
diff --git a/accessible/windows/ia2/ia2AccessibleRelation.h b/accessible/windows/ia2/ia2AccessibleRelation.h
new file mode 100644
index 000000000..faaa31cb0
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleRelation.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#ifndef _NS_ACCESSIBLE_RELATION_WRAP_H
+#define _NS_ACCESSIBLE_RELATION_WRAP_H
+
+#include "Accessible.h"
+#include "IUnknownImpl.h"
+
+#include <utility>
+#include "nsTArray.h"
+
+#include "AccessibleRelation.h"
+
+namespace mozilla {
+namespace a11y {
+
+class ia2AccessibleRelation final : public IAccessibleRelation
+{
+public:
+ ia2AccessibleRelation(RelationType aType, Relation* aRel);
+
+ ia2AccessibleRelation(RelationType aType,
+ nsTArray<RefPtr<Accessible>>&& aTargets) :
+ mType(aType), mTargets(Move(aTargets)) {}
+
+ // IUnknown
+ DECL_IUNKNOWN
+
+ // IAccessibleRelation
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_relationType(
+ /* [retval][out] */ BSTR *relationType);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_localizedRelationType(
+ /* [retval][out] */ BSTR *localizedRelationType);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nTargets(
+ /* [retval][out] */ long *nTargets);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_target(
+ /* [in] */ long targetIndex,
+ /* [retval][out] */ IUnknown **target);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_targets(
+ /* [in] */ long maxTargets,
+ /* [length_is][size_is][out] */ IUnknown **target,
+ /* [retval][out] */ long *nTargets);
+
+ inline bool HasTargets() const
+ { return mTargets.Length(); }
+
+private:
+ ia2AccessibleRelation();
+ ia2AccessibleRelation(const ia2AccessibleRelation&);
+ ia2AccessibleRelation& operator = (const ia2AccessibleRelation&);
+
+ RelationType mType;
+ nsTArray<RefPtr<Accessible> > mTargets;
+};
+
+
+/**
+ * Gecko to IAccessible2 relation types map.
+ */
+
+const WCHAR *const IA2_RELATION_NULL = L"";
+
+#define RELATIONTYPE(geckoType, name, atkType, msaaType, ia2Type) \
+ std::pair<RelationType, const WCHAR *const>(RelationType::geckoType, ia2Type),
+
+static const std::pair<RelationType, const WCHAR *const> sRelationTypePairs[] = {
+#include "RelationTypeMap.h"
+};
+
+#undef RELATIONTYPE
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
+
diff --git a/accessible/windows/ia2/ia2AccessibleTable.cpp b/accessible/windows/ia2/ia2AccessibleTable.cpp
new file mode 100644
index 000000000..6ac6bbab4
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleTable.cpp
@@ -0,0 +1,747 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#include "ia2AccessibleTable.h"
+
+#include "Accessible2.h"
+#include "AccessibleTable_i.c"
+#include "AccessibleTable2_i.c"
+
+#include "AccessibleWrap.h"
+#include "IUnknownImpl.h"
+#include "Statistics.h"
+#include "TableAccessible.h"
+
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+using namespace mozilla::a11y;
+
+// IUnknown
+
+STDMETHODIMP
+ia2AccessibleTable::QueryInterface(REFIID iid, void** ppv)
+{
+ if (!ppv)
+ return E_INVALIDARG;
+
+ *ppv = nullptr;
+
+ if (IID_IAccessibleTable == iid) {
+ statistics::IAccessibleTableUsed();
+ *ppv = static_cast<IAccessibleTable*>(this);
+ (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
+ return S_OK;
+ }
+
+ if (IID_IAccessibleTable2 == iid) {
+ *ppv = static_cast<IAccessibleTable2*>(this);
+ (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// IAccessibleTable
+
+STDMETHODIMP
+ia2AccessibleTable::get_accessibleAt(long aRowIdx, long aColIdx,
+ IUnknown** aAccessible)
+{
+ return get_cellAt(aRowIdx, aColIdx, aAccessible);
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_caption(IUnknown** aAccessible)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aAccessible)
+ return E_INVALIDARG;
+
+ *aAccessible = nullptr;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ AccessibleWrap* caption = static_cast<AccessibleWrap*>(mTable->Caption());
+ if (!caption)
+ return S_FALSE;
+
+ (*aAccessible = static_cast<IAccessible*>(caption))->AddRef();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_childIndex(long aRowIdx, long aColIdx,
+ long* aChildIdx)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aChildIdx)
+ return E_INVALIDARG;
+
+ *aChildIdx = 0;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aRowIdx < 0 || aColIdx < 0 ||
+ static_cast<uint32_t>(aRowIdx) >= mTable->RowCount() ||
+ static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
+ return E_INVALIDARG;
+
+ *aChildIdx = mTable->CellIndexAt(aRowIdx, aColIdx);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_columnDescription(long aColIdx, BSTR* aDescription)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aDescription)
+ return E_INVALIDARG;
+
+ *aDescription = nullptr;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
+ return E_INVALIDARG;
+
+ nsAutoString descr;
+ mTable->ColDescription(aColIdx, descr);
+ if (descr.IsEmpty())
+ return S_FALSE;
+
+ *aDescription = ::SysAllocStringLen(descr.get(), descr.Length());
+ return *aDescription ? S_OK : E_OUTOFMEMORY;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_columnExtentAt(long aRowIdx, long aColIdx,
+ long* aSpan)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aSpan)
+ return E_INVALIDARG;
+
+ *aSpan = 0;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aRowIdx < 0 || aColIdx < 0 ||
+ static_cast<uint32_t>(aRowIdx) >= mTable->RowCount() ||
+ static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
+ return E_INVALIDARG;
+
+ *aSpan = mTable->ColExtentAt(aRowIdx, aColIdx);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_columnHeader(IAccessibleTable** aAccessibleTable,
+ long* aStartingRowIndex)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aAccessibleTable || !aStartingRowIndex)
+ return E_INVALIDARG;
+
+ *aAccessibleTable = nullptr;
+ *aStartingRowIndex = -1;
+ return E_NOTIMPL;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_columnIndex(long aCellIdx, long* aColIdx)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aColIdx)
+ return E_INVALIDARG;
+
+ *aColIdx = 0;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aCellIdx < 0 ||
+ static_cast<uint32_t>(aCellIdx) >= mTable->ColCount() * mTable->RowCount())
+ return E_INVALIDARG;
+
+ *aColIdx = mTable->ColIndexAt(aCellIdx);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_nColumns(long* aColCount)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aColCount)
+ return E_INVALIDARG;
+
+ *aColCount = 0;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ *aColCount = mTable->ColCount();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_nRows(long* aRowCount)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aRowCount)
+ return E_INVALIDARG;
+
+ *aRowCount = 0;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ *aRowCount = mTable->RowCount();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_nSelectedChildren(long* aChildCount)
+{
+ return get_nSelectedCells(aChildCount);
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_nSelectedColumns(long* aColCount)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aColCount)
+ return E_INVALIDARG;
+
+ *aColCount = 0;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ *aColCount = mTable->SelectedColCount();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_nSelectedRows(long* aRowCount)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aRowCount)
+ return E_INVALIDARG;
+
+ *aRowCount = 0;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ *aRowCount = mTable->SelectedRowCount();
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_rowDescription(long aRowIdx, BSTR* aDescription)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aDescription)
+ return E_INVALIDARG;
+
+ *aDescription = nullptr;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
+ return E_INVALIDARG;
+
+ nsAutoString descr;
+ mTable->RowDescription(aRowIdx, descr);
+ if (descr.IsEmpty())
+ return S_FALSE;
+
+ *aDescription = ::SysAllocStringLen(descr.get(), descr.Length());
+ return *aDescription ? S_OK : E_OUTOFMEMORY;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_rowExtentAt(long aRowIdx, long aColIdx, long* aSpan)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aSpan)
+ return E_INVALIDARG;
+
+ *aSpan = 0;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aRowIdx < 0 || aColIdx < 0 ||
+ static_cast<uint32_t>(aRowIdx) >= mTable->RowCount() ||
+ static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
+ return E_INVALIDARG;
+
+ *aSpan = mTable->RowExtentAt(aRowIdx, aColIdx);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_rowHeader(IAccessibleTable** aAccessibleTable,
+ long* aStartingColumnIndex)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aAccessibleTable || !aStartingColumnIndex)
+ return E_INVALIDARG;
+
+ *aAccessibleTable = nullptr;
+ *aStartingColumnIndex = -1;
+ return E_NOTIMPL;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_rowIndex(long aCellIdx, long* aRowIdx)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aRowIdx)
+ return E_INVALIDARG;
+
+ *aRowIdx = 0;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aCellIdx < 0 ||
+ static_cast<uint32_t>(aCellIdx) >= mTable->ColCount() * mTable->RowCount())
+ return E_INVALIDARG;
+
+ *aRowIdx = mTable->RowIndexAt(aCellIdx);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_selectedChildren(long aMaxChildren, long** aChildren,
+ long* aNChildren)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aChildren || !aNChildren)
+ return E_INVALIDARG;
+
+ *aChildren = nullptr;
+ *aNChildren = 0;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ AutoTArray<uint32_t, 30> cellIndices;
+ mTable->SelectedCellIndices(&cellIndices);
+
+ uint32_t maxCells = cellIndices.Length();
+ if (maxCells == 0)
+ return S_FALSE;
+
+ *aChildren = static_cast<LONG*>(moz_xmalloc(sizeof(LONG) * maxCells));
+ *aNChildren = maxCells;
+ for (uint32_t i = 0; i < maxCells; i++)
+ (*aChildren)[i] = cellIndices[i];
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_selectedColumns(long aMaxColumns, long** aColumns,
+ long* aNColumns)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ return get_selectedColumns(aColumns, aNColumns);
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_selectedRows(long aMaxRows, long** aRows, long* aNRows)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ return get_selectedRows(aRows, aNRows);
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_summary(IUnknown** aAccessible)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aAccessible)
+ return E_INVALIDARG;
+
+ // Neither html:table nor xul:tree nor ARIA grid/tree have an ability to
+ // link an accessible object to specify a summary. There is closes method
+ // in Table::summary to get a summary as a string which is not mapped
+ // directly to IAccessible2.
+
+ *aAccessible = nullptr;
+ return S_FALSE;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_isColumnSelected(long aColIdx, boolean* aIsSelected)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aIsSelected)
+ return E_INVALIDARG;
+
+ *aIsSelected = false;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
+ return E_INVALIDARG;
+
+ *aIsSelected = mTable->IsColSelected(aColIdx);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_isRowSelected(long aRowIdx, boolean* aIsSelected)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aIsSelected)
+ return E_INVALIDARG;
+
+ *aIsSelected = false;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
+ return E_INVALIDARG;
+
+ *aIsSelected = mTable->IsRowSelected(aRowIdx);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_isSelected(long aRowIdx, long aColIdx,
+ boolean* aIsSelected)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aIsSelected)
+ return E_INVALIDARG;
+
+ *aIsSelected = false;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aRowIdx < 0 || aColIdx < 0 ||
+ static_cast<uint32_t>(aColIdx) >= mTable->ColCount() ||
+ static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
+ return E_INVALIDARG;
+
+ *aIsSelected = mTable->IsCellSelected(aRowIdx, aColIdx);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::selectRow(long aRowIdx)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
+ return E_INVALIDARG;
+
+ mTable->SelectRow(aRowIdx);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::selectColumn(long aColIdx)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
+ return E_INVALIDARG;
+
+ mTable->SelectCol(aColIdx);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::unselectRow(long aRowIdx)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
+ return E_INVALIDARG;
+
+ mTable->UnselectRow(aRowIdx);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::unselectColumn(long aColIdx)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
+ return E_INVALIDARG;
+
+ mTable->UnselectCol(aColIdx);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_rowColumnExtentsAtIndex(long aCellIdx, long* aRowIdx,
+ long* aColIdx,
+ long* aRowExtents,
+ long* aColExtents,
+ boolean* aIsSelected)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aRowIdx || !aColIdx || !aRowExtents || !aColExtents || !aIsSelected)
+ return E_INVALIDARG;
+
+ *aRowIdx = 0;
+ *aColIdx = 0;
+ *aRowExtents = 0;
+ *aColExtents = 0;
+ *aIsSelected = false;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ if (aCellIdx < 0 ||
+ static_cast<uint32_t>(aCellIdx) >= mTable->ColCount() * mTable->RowCount())
+ return E_INVALIDARG;
+
+ int32_t colIdx = 0, rowIdx = 0;
+ mTable->RowAndColIndicesAt(aCellIdx, &rowIdx, &colIdx);
+ *aRowIdx = rowIdx;
+ *aColIdx = colIdx;
+ *aRowExtents = mTable->RowExtentAt(rowIdx, colIdx);
+ *aColExtents = mTable->ColExtentAt(rowIdx, colIdx);
+ *aIsSelected = mTable->IsCellSelected(rowIdx, colIdx);
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_modelChange(IA2TableModelChange* aModelChange)
+{
+ return E_NOTIMPL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// IAccessibleTable2
+
+STDMETHODIMP
+ia2AccessibleTable::get_cellAt(long aRowIdx, long aColIdx, IUnknown** aCell)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aCell)
+ return E_INVALIDARG;
+
+ *aCell = nullptr;
+
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ AccessibleWrap* cell =
+ static_cast<AccessibleWrap*>(mTable->CellAt(aRowIdx, aColIdx));
+ if (!cell)
+ return E_INVALIDARG;
+
+ (*aCell = static_cast<IAccessible*>(cell))->AddRef();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_nSelectedCells(long* aCellCount)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aCellCount)
+ return E_INVALIDARG;
+
+ *aCellCount = 0;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ *aCellCount = mTable->SelectedCellCount();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_selectedCells(IUnknown*** aCells, long* aNSelectedCells)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aCells || !aNSelectedCells)
+ return E_INVALIDARG;
+
+ *aCells = nullptr;
+ *aNSelectedCells = 0;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ AutoTArray<Accessible*, 30> cells;
+ mTable->SelectedCells(&cells);
+ if (cells.IsEmpty())
+ return S_FALSE;
+
+ *aCells =
+ static_cast<IUnknown**>(::CoTaskMemAlloc(sizeof(IUnknown*) *
+ cells.Length()));
+ if (!*aCells)
+ return E_OUTOFMEMORY;
+
+ for (uint32_t i = 0; i < cells.Length(); i++) {
+ (*aCells)[i] =
+ static_cast<IAccessible*>(static_cast<AccessibleWrap*>(cells[i]));
+ ((*aCells)[i])->AddRef();
+ }
+
+ *aNSelectedCells = cells.Length();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_selectedColumns(long** aColumns, long* aNColumns)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aColumns || !aNColumns)
+ return E_INVALIDARG;
+
+ *aColumns = nullptr;
+ *aNColumns = 0;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ AutoTArray<uint32_t, 30> colIndices;
+ mTable->SelectedColIndices(&colIndices);
+
+ uint32_t maxCols = colIndices.Length();
+ if (maxCols == 0)
+ return S_FALSE;
+
+ *aColumns = static_cast<LONG*>(moz_xmalloc(sizeof(LONG) * maxCols));
+ *aNColumns = maxCols;
+ for (uint32_t i = 0; i < maxCols; i++)
+ (*aColumns)[i] = colIndices[i];
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTable::get_selectedRows(long** aRows, long* aNRows)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aRows || !aNRows)
+ return E_INVALIDARG;
+
+ *aRows = nullptr;
+ *aNRows = 0;
+ if (!mTable)
+ return CO_E_OBJNOTCONNECTED;
+
+ AutoTArray<uint32_t, 30> rowIndices;
+ mTable->SelectedRowIndices(&rowIndices);
+
+ uint32_t maxRows = rowIndices.Length();
+ if (maxRows == 0)
+ return S_FALSE;
+
+ *aRows = static_cast<LONG*>(moz_xmalloc(sizeof(LONG) * maxRows));
+ *aNRows = maxRows;
+ for (uint32_t i = 0; i < maxRows; i++)
+ (*aRows)[i] = rowIndices[i];
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
diff --git a/accessible/windows/ia2/ia2AccessibleTable.h b/accessible/windows/ia2/ia2AccessibleTable.h
new file mode 100644
index 000000000..6738e2dfc
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleTable.h
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#ifndef _ACCESSIBLE_TABLE_H
+#define _ACCESSIBLE_TABLE_H
+
+#include "AccessibleTable.h"
+#include "AccessibleTable2.h"
+
+namespace mozilla {
+namespace a11y {
+
+class TableAccessible;
+
+class ia2AccessibleTable : public IAccessibleTable,
+ public IAccessibleTable2
+{
+public:
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID, void**);
+
+ // IAccessibleTable
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_accessibleAt(
+ /* [in] */ long row,
+ /* [in] */ long column,
+ /* [retval][out] */ IUnknown **accessible);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_caption(
+ /* [retval][out] */ IUnknown **accessible);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_childIndex(
+ /* [in] */ long rowIndex,
+ /* [in] */ long columnIndex,
+ /* [retval][out] */ long *childIndex);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_columnDescription(
+ /* [in] */ long column,
+ /* [retval][out] */ BSTR *description);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_columnExtentAt(
+ /* [in] */ long row,
+ /* [in] */ long column,
+ /* [retval][out] */ long *nColumnsSpanned);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_columnHeader(
+ /* [out] */ IAccessibleTable **accessibleTable,
+ /* [retval][out] */ long *startingRowIndex);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_columnIndex(
+ /* [in] */ long childIndex,
+ /* [retval][out] */ long *columnIndex);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nColumns(
+ /* [retval][out] */ long *columnCount);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nRows(
+ /* [retval][out] */ long *rowCount);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nSelectedChildren(
+ /* [retval][out] */ long *childCount);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nSelectedColumns(
+ /* [retval][out] */ long *columnCount);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nSelectedRows(
+ /* [retval][out] */ long *rowCount);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_rowDescription(
+ /* [in] */ long row,
+ /* [retval][out] */ BSTR *description);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_rowExtentAt(
+ /* [in] */ long row,
+ /* [in] */ long column,
+ /* [retval][out] */ long *nRowsSpanned);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_rowHeader(
+ /* [out] */ IAccessibleTable **accessibleTable,
+ /* [retval][out] */ long *startingColumnIndex);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_rowIndex(
+ /* [in] */ long childIndex,
+ /* [retval][out] */ long *rowIndex);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_selectedChildren(
+ /* [in] */ long maxChildren,
+ /* [length_is][length_is][size_is][size_is][out] */ long **children,
+ /* [retval][out] */ long *nChildren);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_selectedColumns(
+ /* [in] */ long maxColumns,
+ /* [length_is][length_is][size_is][size_is][out] */ long **columns,
+ /* [retval][out] */ long *nColumns);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_selectedRows(
+ /* [in] */ long maxRows,
+ /* [length_is][length_is][size_is][size_is][out] */ long **rows,
+ /* [retval][out] */ long *nRows);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_summary(
+ /* [retval][out] */ IUnknown **accessible);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_isColumnSelected(
+ /* [in] */ long column,
+ /* [retval][out] */ boolean *isSelected);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_isRowSelected(
+ /* [in] */ long row,
+ /* [retval][out] */ boolean *isSelected);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_isSelected(
+ /* [in] */ long row,
+ /* [in] */ long column,
+ /* [retval][out] */ boolean *isSelected);
+
+ virtual HRESULT STDMETHODCALLTYPE selectRow(
+ /* [in] */ long row);
+
+ virtual HRESULT STDMETHODCALLTYPE selectColumn(
+ /* [in] */ long column);
+
+ virtual HRESULT STDMETHODCALLTYPE unselectRow(
+ /* [in] */ long row);
+
+ virtual HRESULT STDMETHODCALLTYPE unselectColumn(
+ /* [in] */ long column);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_rowColumnExtentsAtIndex(
+ /* [in] */ long index,
+ /* [out] */ long *row,
+ /* [out] */ long *column,
+ /* [out] */ long *rowExtents,
+ /* [out] */ long *columnExtents,
+ /* [retval][out] */ boolean *isSelected);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_modelChange(
+ /* [retval][out] */ IA2TableModelChange *modelChange);
+
+
+ // IAccessibleTable2
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_cellAt(
+ /* [in] */ long row,
+ /* [in] */ long column,
+ /* [out, retval] */ IUnknown **cell);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nSelectedCells(
+ /* [out, retval] */ long *cellCount);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_selectedCells(
+ /* [out, size_is(,*nSelectedCells,)] */ IUnknown ***cells,
+ /* [out, retval] */ long *nSelectedCells);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_selectedColumns(
+ /* [out, size_is(,*nColumns)] */ long **selectedColumns,
+ /* [out, retval] */ long *nColumns);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_selectedRows(
+ /* [out, size_is(,*nRows)] */ long **selectedRows,
+ /* [out, retval] */ long *nRows);
+
+protected:
+ ia2AccessibleTable(TableAccessible* aTable) : mTable(aTable) {}
+
+ TableAccessible* mTable;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/windows/ia2/ia2AccessibleTableCell.cpp b/accessible/windows/ia2/ia2AccessibleTableCell.cpp
new file mode 100644
index 000000000..e625a7049
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleTableCell.cpp
@@ -0,0 +1,257 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#include "ia2AccessibleTableCell.h"
+
+#include "Accessible2.h"
+#include "AccessibleTable2_i.c"
+#include "AccessibleTableCell_i.c"
+
+#include "AccessibleWrap.h"
+#include "TableAccessible.h"
+#include "TableCellAccessible.h"
+#include "IUnknownImpl.h"
+
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+using namespace mozilla::a11y;
+
+// IUnknown
+
+STDMETHODIMP
+ia2AccessibleTableCell::QueryInterface(REFIID iid, void** ppv)
+{
+ if (!ppv)
+ return E_INVALIDARG;
+
+ *ppv = nullptr;
+
+ if (IID_IAccessibleTableCell == iid) {
+ *ppv = static_cast<IAccessibleTableCell*>(this);
+ (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// IAccessibleTableCell
+
+STDMETHODIMP
+ia2AccessibleTableCell::get_table(IUnknown** aTable)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aTable)
+ return E_INVALIDARG;
+
+ *aTable = nullptr;
+ if (!mTableCell)
+ return CO_E_OBJNOTCONNECTED;
+
+ TableAccessible* table = mTableCell->Table();
+ if (!table)
+ return E_FAIL;
+
+ AccessibleWrap* wrap = static_cast<AccessibleWrap*>(table->AsAccessible());
+ *aTable = static_cast<IAccessible*>(wrap);
+ (*aTable)->AddRef();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTableCell::get_columnExtent(long* aSpan)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aSpan)
+ return E_INVALIDARG;
+
+ *aSpan = 0;
+ if (!mTableCell)
+ return CO_E_OBJNOTCONNECTED;
+
+ *aSpan = mTableCell->ColExtent();
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTableCell::get_columnHeaderCells(IUnknown*** aCellAccessibles,
+ long* aNColumnHeaderCells)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aCellAccessibles || !aNColumnHeaderCells)
+ return E_INVALIDARG;
+
+ *aCellAccessibles = nullptr;
+ *aNColumnHeaderCells = 0;
+ if (!mTableCell)
+ return CO_E_OBJNOTCONNECTED;
+
+ AutoTArray<Accessible*, 10> cells;
+ mTableCell->ColHeaderCells(&cells);
+
+ *aNColumnHeaderCells = cells.Length();
+ *aCellAccessibles =
+ static_cast<IUnknown**>(::CoTaskMemAlloc(sizeof(IUnknown*) *
+ cells.Length()));
+
+ if (!*aCellAccessibles)
+ return E_OUTOFMEMORY;
+
+ for (uint32_t i = 0; i < cells.Length(); i++) {
+ AccessibleWrap* cell = static_cast<AccessibleWrap*>(cells[i]);
+ (*aCellAccessibles)[i] = static_cast<IAccessible*>(cell);
+ (*aCellAccessibles)[i]->AddRef();
+ }
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTableCell::get_columnIndex(long* aColIdx)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aColIdx)
+ return E_INVALIDARG;
+
+ *aColIdx = -1;
+ if (!mTableCell)
+ return CO_E_OBJNOTCONNECTED;
+
+ *aColIdx = mTableCell->ColIdx();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTableCell::get_rowExtent(long* aSpan)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aSpan)
+ return E_INVALIDARG;
+
+ *aSpan = 0;
+ if (!mTableCell)
+ return CO_E_OBJNOTCONNECTED;
+
+ *aSpan = mTableCell->RowExtent();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTableCell::get_rowHeaderCells(IUnknown*** aCellAccessibles,
+ long* aNRowHeaderCells)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aCellAccessibles || !aNRowHeaderCells)
+ return E_INVALIDARG;
+
+ *aCellAccessibles = nullptr;
+ *aNRowHeaderCells = 0;
+ if (!mTableCell)
+ return CO_E_OBJNOTCONNECTED;
+
+ AutoTArray<Accessible*, 10> cells;
+ mTableCell->RowHeaderCells(&cells);
+
+ *aNRowHeaderCells = cells.Length();
+ *aCellAccessibles =
+ static_cast<IUnknown**>(::CoTaskMemAlloc(sizeof(IUnknown*) *
+ cells.Length()));
+ if (!*aCellAccessibles)
+ return E_OUTOFMEMORY;
+
+ for (uint32_t i = 0; i < cells.Length(); i++) {
+ AccessibleWrap* cell = static_cast<AccessibleWrap*>(cells[i]);
+ (*aCellAccessibles)[i] = static_cast<IAccessible*>(cell);
+ (*aCellAccessibles)[i]->AddRef();
+ }
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTableCell::get_rowIndex(long* aRowIdx)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aRowIdx)
+ return E_INVALIDARG;
+
+ *aRowIdx = -1;
+ if (!mTableCell)
+ return CO_E_OBJNOTCONNECTED;
+
+ *aRowIdx = mTableCell->RowIdx();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTableCell::get_rowColumnExtents(long* aRowIdx, long* aColIdx,
+ long* aRowExtents,
+ long* aColExtents,
+ boolean* aIsSelected)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aRowIdx || !aColIdx || !aRowExtents || !aColExtents || !aIsSelected)
+ return E_INVALIDARG;
+
+ *aRowIdx = *aColIdx = *aRowExtents = *aColExtents = 0;
+ *aIsSelected = false;
+ if (!mTableCell)
+ return CO_E_OBJNOTCONNECTED;
+
+ *aRowIdx = mTableCell->RowIdx();
+ *aColIdx = mTableCell->ColIdx();
+ *aRowExtents = mTableCell->RowExtent();
+ *aColExtents = mTableCell->ColExtent();
+ *aIsSelected = mTableCell->Selected();
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleTableCell::get_isSelected(boolean* aIsSelected)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aIsSelected)
+ return E_INVALIDARG;
+
+ *aIsSelected = false;
+ if (!mTableCell)
+ return CO_E_OBJNOTCONNECTED;
+
+ *aIsSelected = mTableCell->Selected();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
diff --git a/accessible/windows/ia2/ia2AccessibleTableCell.h b/accessible/windows/ia2/ia2AccessibleTableCell.h
new file mode 100644
index 000000000..883ca2875
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleTableCell.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#ifndef _ACCESSIBLE_TABLECELL_H
+#define _ACCESSIBLE_TABLECELL_H
+
+#include "AccessibleTableCell.h"
+
+namespace mozilla {
+namespace a11y {
+class TableCellAccessible;
+
+class ia2AccessibleTableCell : public IAccessibleTableCell
+{
+public:
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID, void**);
+
+ // IAccessibleTableCell
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_table(
+ /* [out, retval] */ IUnknown **table);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_columnExtent(
+ /* [out, retval] */ long *nColumnsSpanned);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_columnHeaderCells(
+ /* [out, size_is(,*nColumnHeaderCells,)] */ IUnknown ***cellAccessibles,
+ /* [out, retval] */ long *nColumnHeaderCells);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_columnIndex(
+ /* [out, retval] */ long *columnIndex);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_rowExtent(
+ /* [out, retval] */ long *nRowsSpanned);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_rowHeaderCells(
+ /* [out, size_is(,*nRowHeaderCells,)] */ IUnknown ***cellAccessibles,
+ /* [out, retval] */ long *nRowHeaderCells);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_rowIndex(
+ /* [out, retval] */ long *rowIndex);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_rowColumnExtents(
+ /* [out] */ long *row,
+ /* [out] */ long *column,
+ /* [out] */ long *rowExtents,
+ /* [out] */ long *columnExtents,
+ /* [out, retval] */ boolean *isSelected);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_isSelected(
+ /* [out, retval] */ boolean *isSelected);
+
+protected:
+ ia2AccessibleTableCell(TableCellAccessible* aTableCell) :
+ mTableCell(aTableCell) {}
+
+ TableCellAccessible* mTableCell;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/windows/ia2/ia2AccessibleText.cpp b/accessible/windows/ia2/ia2AccessibleText.cpp
new file mode 100644
index 000000000..7ac766f30
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleText.cpp
@@ -0,0 +1,598 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#include "ia2AccessibleText.h"
+
+#include "Accessible2.h"
+#include "AccessibleText_i.c"
+
+#include "HyperTextAccessibleWrap.h"
+#include "HyperTextAccessible-inl.h"
+#include "ProxyWrappers.h"
+#include "mozilla/ClearOnShutdown.h"
+
+using namespace mozilla::a11y;
+
+StaticRefPtr<HyperTextAccessibleWrap> ia2AccessibleText::sLastTextChangeAcc;
+StaticAutoPtr<nsString> ia2AccessibleText::sLastTextChangeString;
+uint32_t ia2AccessibleText::sLastTextChangeStart = 0;
+uint32_t ia2AccessibleText::sLastTextChangeEnd = 0;
+bool ia2AccessibleText::sLastTextChangeWasInsert = false;
+
+// IAccessibleText
+
+STDMETHODIMP
+ia2AccessibleText::addSelection(long aStartOffset, long aEndOffset)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ return textAcc->AddToSelection(aStartOffset, aEndOffset) ?
+ S_OK : E_INVALIDARG;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::get_attributes(long aOffset, long *aStartOffset,
+ long *aEndOffset, BSTR *aTextAttributes)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aStartOffset || !aEndOffset || !aTextAttributes)
+ return E_INVALIDARG;
+
+ *aStartOffset = 0;
+ *aEndOffset = 0;
+ *aTextAttributes = nullptr;
+
+ int32_t startOffset = 0, endOffset = 0;
+ HRESULT hr;
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct()) {
+ return CO_E_OBJNOTCONNECTED;
+ }
+
+ nsCOMPtr<nsIPersistentProperties> attributes =
+ textAcc->TextAttributes(true, aOffset, &startOffset, &endOffset);
+
+ hr = AccessibleWrap::ConvertToIA2Attributes(attributes, aTextAttributes);
+ if (FAILED(hr))
+ return hr;
+
+ *aStartOffset = startOffset;
+ *aEndOffset = endOffset;
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::get_caretOffset(long *aOffset)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aOffset)
+ return E_INVALIDARG;
+
+ *aOffset = -1;
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct()) {
+ return CO_E_OBJNOTCONNECTED;
+ }
+
+ *aOffset = textAcc->CaretOffset();
+
+ return *aOffset != -1 ? S_OK : S_FALSE;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::get_characterExtents(long aOffset,
+ enum IA2CoordinateType aCoordType,
+ long* aX, long* aY,
+ long* aWidth, long* aHeight)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aX || !aY || !aWidth || !aHeight)
+ return E_INVALIDARG;
+ *aX = *aY = *aWidth = *aHeight = 0;
+
+ uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
+ nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
+ nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
+ nsIntRect rect;
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ rect = textAcc->CharBounds(aOffset, geckoCoordType);
+
+ *aX = rect.x;
+ *aY = rect.y;
+ *aWidth = rect.width;
+ *aHeight = rect.height;
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::get_nSelections(long* aNSelections)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aNSelections)
+ return E_INVALIDARG;
+ *aNSelections = 0;
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct()) {
+ return CO_E_OBJNOTCONNECTED;
+ }
+
+ *aNSelections = textAcc->SelectionCount();
+
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::get_offsetAtPoint(long aX, long aY,
+ enum IA2CoordinateType aCoordType,
+ long* aOffset)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aOffset)
+ return E_INVALIDARG;
+ *aOffset = 0;
+
+ uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
+ nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
+ nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct()) {
+ return CO_E_OBJNOTCONNECTED;
+ }
+
+ *aOffset = textAcc->OffsetAtPoint(aX, aY, geckoCoordType);
+
+ return *aOffset == -1 ? S_FALSE : S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::get_selection(long aSelectionIndex, long* aStartOffset,
+ long* aEndOffset)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aStartOffset || !aEndOffset)
+ return E_INVALIDARG;
+ *aStartOffset = *aEndOffset = 0;
+
+ int32_t startOffset = 0, endOffset = 0;
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct()) {
+ return CO_E_OBJNOTCONNECTED;
+ }
+
+ if (!textAcc->SelectionBoundsAt(aSelectionIndex, &startOffset, &endOffset)) {
+ return E_INVALIDARG;
+ }
+
+ *aStartOffset = startOffset;
+ *aEndOffset = endOffset;
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR* aText)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aText)
+ return E_INVALIDARG;
+
+ *aText = nullptr;
+
+ nsAutoString text;
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct()) {
+ return CO_E_OBJNOTCONNECTED;
+ }
+
+ if (!textAcc->IsValidRange(aStartOffset, aEndOffset)) {
+ return E_INVALIDARG;
+ }
+
+ textAcc->TextSubstring(aStartOffset, aEndOffset, text);
+
+ if (text.IsEmpty())
+ return S_FALSE;
+
+ *aText = ::SysAllocStringLen(text.get(), text.Length());
+ return *aText ? S_OK : E_OUTOFMEMORY;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::get_textBeforeOffset(long aOffset,
+ enum IA2TextBoundaryType aBoundaryType,
+ long* aStartOffset, long* aEndOffset,
+ BSTR* aText)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aStartOffset || !aEndOffset || !aText)
+ return E_INVALIDARG;
+
+ *aStartOffset = *aEndOffset = 0;
+ *aText = nullptr;
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!textAcc->IsValidOffset(aOffset))
+ return E_INVALIDARG;
+
+ nsAutoString text;
+ int32_t startOffset = 0, endOffset = 0;
+
+ if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
+ startOffset = 0;
+ endOffset = textAcc->CharacterCount();
+ textAcc->TextSubstring(startOffset, endOffset, text);
+ } else {
+ AccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
+ if (boundaryType == -1)
+ return S_FALSE;
+
+ textAcc->TextBeforeOffset(aOffset, boundaryType, &startOffset, &endOffset, text);
+ }
+
+ *aStartOffset = startOffset;
+ *aEndOffset = endOffset;
+
+ if (text.IsEmpty())
+ return S_FALSE;
+
+ *aText = ::SysAllocStringLen(text.get(), text.Length());
+ return *aText ? S_OK : E_OUTOFMEMORY;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::get_textAfterOffset(long aOffset,
+ enum IA2TextBoundaryType aBoundaryType,
+ long* aStartOffset, long* aEndOffset,
+ BSTR* aText)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aStartOffset || !aEndOffset || !aText)
+ return E_INVALIDARG;
+
+ *aStartOffset = 0;
+ *aEndOffset = 0;
+ *aText = nullptr;
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!textAcc->IsValidOffset(aOffset))
+ return E_INVALIDARG;
+
+ nsAutoString text;
+ int32_t startOffset = 0, endOffset = 0;
+
+ if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
+ startOffset = 0;
+ endOffset = textAcc->CharacterCount();
+ textAcc->TextSubstring(startOffset, endOffset, text);
+ } else {
+ AccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
+ if (boundaryType == -1)
+ return S_FALSE;
+ textAcc->TextAfterOffset(aOffset, boundaryType, &startOffset, &endOffset, text);
+ }
+
+ *aStartOffset = startOffset;
+ *aEndOffset = endOffset;
+
+ if (text.IsEmpty())
+ return S_FALSE;
+
+ *aText = ::SysAllocStringLen(text.get(), text.Length());
+ return *aText ? S_OK : E_OUTOFMEMORY;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::get_textAtOffset(long aOffset,
+ enum IA2TextBoundaryType aBoundaryType,
+ long* aStartOffset, long* aEndOffset,
+ BSTR* aText)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aStartOffset || !aEndOffset || !aText)
+ return E_INVALIDARG;
+
+ *aStartOffset = *aEndOffset = 0;
+ *aText = nullptr;
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!textAcc->IsValidOffset(aOffset))
+ return E_INVALIDARG;
+
+ nsAutoString text;
+ int32_t startOffset = 0, endOffset = 0;
+ if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
+ startOffset = 0;
+ endOffset = textAcc->CharacterCount();
+ textAcc->TextSubstring(startOffset, endOffset, text);
+ } else {
+ AccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
+ if (boundaryType == -1)
+ return S_FALSE;
+ textAcc->TextAtOffset(aOffset, boundaryType, &startOffset, &endOffset, text);
+ }
+
+ *aStartOffset = startOffset;
+ *aEndOffset = endOffset;
+
+ if (text.IsEmpty())
+ return S_FALSE;
+
+ *aText = ::SysAllocStringLen(text.get(), text.Length());
+ return *aText ? S_OK : E_OUTOFMEMORY;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::removeSelection(long aSelectionIndex)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ return textAcc->RemoveFromSelection(aSelectionIndex) ?
+ S_OK : E_INVALIDARG;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::setCaretOffset(long aOffset)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!textAcc->IsValidOffset(aOffset))
+ return E_INVALIDARG;
+
+ textAcc->SetCaretOffset(aOffset);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::setSelection(long aSelectionIndex, long aStartOffset,
+ long aEndOffset)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ return textAcc->SetSelectionBoundsAt(aSelectionIndex, aStartOffset, aEndOffset) ?
+ S_OK : E_INVALIDARG;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::get_nCharacters(long* aNCharacters)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aNCharacters)
+ return E_INVALIDARG;
+ *aNCharacters = 0;
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ *aNCharacters = textAcc->CharacterCount();
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex,
+ enum IA2ScrollType aScrollType)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!textAcc->IsValidRange(aStartIndex, aEndIndex))
+ return E_INVALIDARG;
+
+ textAcc->ScrollSubstringTo(aStartIndex, aEndIndex, aScrollType);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex,
+ enum IA2CoordinateType aCoordType,
+ long aX, long aY)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
+ nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
+ nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
+
+ MOZ_ASSERT(!HyperTextProxyFor(this));
+
+ HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+ if (textAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ if (!textAcc->IsValidRange(aStartIndex, aEndIndex))
+ return E_INVALIDARG;
+
+ textAcc->ScrollSubstringToPoint(aStartIndex, aEndIndex,
+ geckoCoordType, aX, aY);
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::get_newText(IA2TextSegment *aNewText)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ return GetModifiedText(true, aNewText);
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleText::get_oldText(IA2TextSegment *aOldText)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ return GetModifiedText(false, aOldText);
+
+ A11Y_TRYBLOCK_END
+}
+
+// ia2AccessibleText
+
+HRESULT
+ia2AccessibleText::GetModifiedText(bool aGetInsertedText,
+ IA2TextSegment *aText)
+{
+ if (!aText)
+ return E_INVALIDARG;
+
+ if (!sLastTextChangeAcc)
+ return S_OK;
+
+ if (aGetInsertedText != sLastTextChangeWasInsert)
+ return S_OK;
+
+ if (sLastTextChangeAcc != this)
+ return S_OK;
+
+ aText->start = sLastTextChangeStart;
+ aText->end = sLastTextChangeEnd;
+
+ if (sLastTextChangeString->IsEmpty())
+ return S_FALSE;
+
+ aText->text = ::SysAllocStringLen(sLastTextChangeString->get(), sLastTextChangeString->Length());
+ return aText->text ? S_OK : E_OUTOFMEMORY;
+}
+
+AccessibleTextBoundary
+ia2AccessibleText::GetGeckoTextBoundary(enum IA2TextBoundaryType aBoundaryType)
+{
+ switch (aBoundaryType) {
+ case IA2_TEXT_BOUNDARY_CHAR:
+ return nsIAccessibleText::BOUNDARY_CHAR;
+ case IA2_TEXT_BOUNDARY_WORD:
+ return nsIAccessibleText::BOUNDARY_WORD_START;
+ case IA2_TEXT_BOUNDARY_LINE:
+ return nsIAccessibleText::BOUNDARY_LINE_START;
+ //case IA2_TEXT_BOUNDARY_SENTENCE:
+ //case IA2_TEXT_BOUNDARY_PARAGRAPH:
+ // XXX: not implemented
+ default:
+ return -1;
+ }
+}
+
+void
+ia2AccessibleText::InitTextChangeData()
+{
+ ClearOnShutdown(&sLastTextChangeAcc);
+ ClearOnShutdown(&sLastTextChangeString);
+}
+
+void
+ia2AccessibleText::UpdateTextChangeData(HyperTextAccessibleWrap* aAcc,
+ bool aInsert, const nsString& aStr,
+ int32_t aStart, uint32_t aLen)
+{
+ if (!sLastTextChangeString)
+ sLastTextChangeString = new nsString();
+
+ sLastTextChangeAcc = aAcc;
+ sLastTextChangeStart = aStart;
+ sLastTextChangeEnd = aStart + aLen;
+ sLastTextChangeWasInsert = aInsert;
+ *sLastTextChangeString = aStr;
+}
diff --git a/accessible/windows/ia2/ia2AccessibleText.h b/accessible/windows/ia2/ia2AccessibleText.h
new file mode 100644
index 000000000..a513e44a2
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleText.h
@@ -0,0 +1,275 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#ifndef _ACCESSIBLE_TEXT_H
+#define _ACCESSIBLE_TEXT_H
+
+#include "nsIAccessibleText.h"
+
+#include "AccessibleText.h"
+
+namespace mozilla {
+namespace a11y {
+class HyperTextAccessibleWrap;
+
+class ia2AccessibleText: public IAccessibleText
+{
+public:
+
+ // IAccessibleText
+ virtual HRESULT STDMETHODCALLTYPE addSelection(
+ /* [in] */ long startOffset,
+ /* [in] */ long endOffset);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_attributes(
+ /* [in] */ long offset,
+ /* [out] */ long *startOffset,
+ /* [out] */ long *endOffset,
+ /* [retval][out] */ BSTR *textAttributes);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_caretOffset(
+ /* [retval][out] */ long *offset);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_characterExtents(
+ /* [in] */ long offset,
+ /* [in] */ enum IA2CoordinateType coordType,
+ /* [out] */ long *x,
+ /* [out] */ long *y,
+ /* [out] */ long *width,
+ /* [retval][out] */ long *height);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nSelections(
+ /* [retval][out] */ long *nSelections);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_offsetAtPoint(
+ /* [in] */ long x,
+ /* [in] */ long y,
+ /* [in] */ enum IA2CoordinateType coordType,
+ /* [retval][out] */ long *offset);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_selection(
+ /* [in] */ long selectionIndex,
+ /* [out] */ long *startOffset,
+ /* [retval][out] */ long *endOffset);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_text(
+ /* [in] */ long startOffset,
+ /* [in] */ long endOffset,
+ /* [retval][out] */ BSTR *text);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_textBeforeOffset(
+ /* [in] */ long offset,
+ /* [in] */ enum IA2TextBoundaryType boundaryType,
+ /* [out] */ long *startOffset,
+ /* [out] */ long *endOffset,
+ /* [retval][out] */ BSTR *text);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_textAfterOffset(
+ /* [in] */ long offset,
+ /* [in] */ enum IA2TextBoundaryType boundaryType,
+ /* [out] */ long *startOffset,
+ /* [out] */ long *endOffset,
+ /* [retval][out] */ BSTR *text);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_textAtOffset(
+ /* [in] */ long offset,
+ /* [in] */ enum IA2TextBoundaryType boundaryType,
+ /* [out] */ long *startOffset,
+ /* [out] */ long *endOffset,
+ /* [retval][out] */ BSTR *text);
+
+ virtual HRESULT STDMETHODCALLTYPE removeSelection(
+ /* [in] */ long selectionIndex);
+
+ virtual HRESULT STDMETHODCALLTYPE setCaretOffset(
+ /* [in] */ long offset);
+
+ virtual HRESULT STDMETHODCALLTYPE setSelection(
+ /* [in] */ long selectionIndex,
+ /* [in] */ long startOffset,
+ /* [in] */ long endOffset);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nCharacters(
+ /* [retval][out] */ long *nCharacters);
+
+ virtual HRESULT STDMETHODCALLTYPE scrollSubstringTo(
+ /* [in] */ long startIndex,
+ /* [in] */ long endIndex,
+ /* [in] */ enum IA2ScrollType scrollType);
+
+ virtual HRESULT STDMETHODCALLTYPE scrollSubstringToPoint(
+ /* [in] */ long startIndex,
+ /* [in] */ long endIndex,
+ /* [in] */ enum IA2CoordinateType coordinateType,
+ /* [in] */ long x,
+ /* [in] */ long y);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_newText(
+ /* [retval][out] */ IA2TextSegment *newText);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_oldText(
+ /* [retval][out] */ IA2TextSegment *oldText);
+
+ static void InitTextChangeData();
+ static void UpdateTextChangeData(HyperTextAccessibleWrap* aAcc, bool aInsert,
+ const nsString& aStr, int32_t aStart,
+ uint32_t aLen);
+
+protected:
+ static StaticRefPtr<HyperTextAccessibleWrap> sLastTextChangeAcc;
+ static StaticAutoPtr<nsString> sLastTextChangeString;
+ static bool sLastTextChangeWasInsert;
+ static uint32_t sLastTextChangeStart;
+ static uint32_t sLastTextChangeEnd;
+
+private:
+ HRESULT GetModifiedText(bool aGetInsertedText, IA2TextSegment *aNewText);
+ AccessibleTextBoundary GetGeckoTextBoundary(enum IA2TextBoundaryType coordinateType);
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+
+#define FORWARD_IACCESSIBLETEXT(Class) \
+virtual HRESULT STDMETHODCALLTYPE addSelection(long startOffset, \
+ long endOffset) \
+{ \
+ return Class::addSelection(startOffset, endOffset); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_attributes(long offset, \
+ long *startOffset, \
+ long *endOffset, \
+ BSTR *textAttributes) \
+{ \
+ return Class::get_attributes(offset, startOffset, endOffset, textAttributes);\
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_caretOffset(long *offset) \
+{ \
+ return Class::get_caretOffset(offset); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_characterExtents(long offset, \
+ enum IA2CoordinateType coordType,\
+ long *x, \
+ long *y, \
+ long *width, \
+ long *height) \
+{ \
+ return Class::get_characterExtents(offset, coordType, x, y, width, height); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_nSelections(long *nSelections) \
+{ \
+ return Class::get_nSelections(nSelections); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_offsetAtPoint(long x, \
+ long y, \
+ enum IA2CoordinateType coordType,\
+ long *offset) \
+{ \
+ return Class::get_offsetAtPoint(x, y, coordType, offset); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_selection(long selectionIndex, \
+ long *startOffset, \
+ long *endOffset) \
+{ \
+ return Class::get_selection(selectionIndex, startOffset, endOffset); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_text(long startOffset, \
+ long endOffset, \
+ BSTR *text) \
+{ \
+ return Class::get_text(startOffset, endOffset, text); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_textBeforeOffset(long offset, \
+ enum IA2TextBoundaryType boundaryType,\
+ long *startOffset, \
+ long *endOffset, \
+ BSTR *text) \
+{ \
+ return Class::get_textBeforeOffset(offset, boundaryType, \
+ startOffset, endOffset, text); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_textAfterOffset(long offset, \
+ enum IA2TextBoundaryType boundaryType,\
+ long *startOffset, \
+ long *endOffset, \
+ BSTR *text) \
+{ \
+ return Class::get_textAfterOffset(offset, boundaryType, \
+ startOffset, endOffset, text); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_textAtOffset(long offset, \
+ enum IA2TextBoundaryType boundaryType,\
+ long *startOffset, \
+ long *endOffset, \
+ BSTR *text) \
+{ \
+ return Class::get_textAtOffset(offset, boundaryType, \
+ startOffset, endOffset, text); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE removeSelection(long selectionIndex) \
+{ \
+ return Class::removeSelection(selectionIndex); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE setCaretOffset(long offset) \
+{ \
+ return Class::setCaretOffset(offset); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE setSelection(long selectionIndex, \
+ long startOffset, \
+ long endOffset) \
+{ \
+ return Class::setSelection(selectionIndex, startOffset, endOffset); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_nCharacters(long *nCharacters) \
+{ \
+ return Class::get_nCharacters(nCharacters); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE scrollSubstringTo(long startIndex, \
+ long endIndex, \
+ enum IA2ScrollType scrollType)\
+{ \
+ return Class::scrollSubstringTo(startIndex, endIndex, scrollType); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE scrollSubstringToPoint(long startIndex, \
+ long endIndex, \
+ enum IA2CoordinateType coordinateType,\
+ long x, \
+ long y) \
+{ \
+ return Class::scrollSubstringToPoint(startIndex, endIndex, \
+ coordinateType, x, y); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_newText(IA2TextSegment *newText) \
+{ \
+ return Class::get_newText(newText); \
+} \
+ \
+virtual HRESULT STDMETHODCALLTYPE get_oldText(IA2TextSegment *oldText) \
+{ \
+ return Class::get_oldText(oldText); \
+} \
+
+#endif
+
diff --git a/accessible/windows/ia2/ia2AccessibleValue.cpp b/accessible/windows/ia2/ia2AccessibleValue.cpp
new file mode 100644
index 000000000..e33442295
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleValue.cpp
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#include "ia2AccessibleValue.h"
+
+#include "AccessibleValue_i.c"
+
+#include "AccessibleWrap.h"
+#include "Accessible-inl.h"
+#include "IUnknownImpl.h"
+
+#include "mozilla/FloatingPoint.h"
+
+using namespace mozilla::a11y;
+
+// IUnknown
+
+STDMETHODIMP
+ia2AccessibleValue::QueryInterface(REFIID iid, void** ppv)
+{
+ if (!ppv)
+ return E_INVALIDARG;
+
+ *ppv = nullptr;
+
+ if (IID_IAccessibleValue == iid) {
+ AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
+ if (valueAcc->HasNumericValue()) {
+ *ppv = static_cast<IAccessibleValue*>(this);
+ valueAcc->AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+ }
+
+ return E_NOINTERFACE;
+}
+
+// IAccessibleValue
+
+STDMETHODIMP
+ia2AccessibleValue::get_currentValue(VARIANT* aCurrentValue)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aCurrentValue)
+ return E_INVALIDARG;
+
+ VariantInit(aCurrentValue);
+
+ AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
+ double currentValue;
+ MOZ_ASSERT(!valueAcc->IsProxy());
+ if (valueAcc->IsDefunct()) {
+ return CO_E_OBJNOTCONNECTED;
+ }
+
+ currentValue = valueAcc->CurValue();
+
+ if (IsNaN(currentValue))
+ return S_FALSE;
+
+ aCurrentValue->vt = VT_R8;
+ aCurrentValue->dblVal = currentValue;
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleValue::setCurrentValue(VARIANT aValue)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (aValue.vt != VT_R8)
+ return E_INVALIDARG;
+
+ AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
+ MOZ_ASSERT(!valueAcc->IsProxy());
+
+ if (valueAcc->IsDefunct())
+ return CO_E_OBJNOTCONNECTED;
+
+ return valueAcc->SetCurValue(aValue.dblVal) ? S_OK : E_FAIL;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleValue::get_maximumValue(VARIANT* aMaximumValue)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aMaximumValue)
+ return E_INVALIDARG;
+
+ VariantInit(aMaximumValue);
+
+ AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
+ double maximumValue;
+ MOZ_ASSERT(!valueAcc->IsProxy());
+ if (valueAcc->IsDefunct()) {
+ return CO_E_OBJNOTCONNECTED;
+ }
+
+ maximumValue = valueAcc->MaxValue();
+
+ if (IsNaN(maximumValue))
+ return S_FALSE;
+
+ aMaximumValue->vt = VT_R8;
+ aMaximumValue->dblVal = maximumValue;
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
+STDMETHODIMP
+ia2AccessibleValue::get_minimumValue(VARIANT* aMinimumValue)
+{
+ A11Y_TRYBLOCK_BEGIN
+
+ if (!aMinimumValue)
+ return E_INVALIDARG;
+
+ VariantInit(aMinimumValue);
+
+ AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
+ double minimumValue;
+ MOZ_ASSERT(!valueAcc->IsProxy());
+ if (valueAcc->IsDefunct()) {
+ return CO_E_OBJNOTCONNECTED;
+ }
+
+ minimumValue = valueAcc->MinValue();
+
+ if (IsNaN(minimumValue))
+ return S_FALSE;
+
+ aMinimumValue->vt = VT_R8;
+ aMinimumValue->dblVal = minimumValue;
+ return S_OK;
+
+ A11Y_TRYBLOCK_END
+}
+
diff --git a/accessible/windows/ia2/ia2AccessibleValue.h b/accessible/windows/ia2/ia2AccessibleValue.h
new file mode 100644
index 000000000..97ce5ea59
--- /dev/null
+++ b/accessible/windows/ia2/ia2AccessibleValue.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* 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/. */
+
+#ifndef _ACCESSIBLE_VALUE_H
+#define _ACCESSIBLE_VALUE_H
+
+#include "AccessibleValue.h"
+
+namespace mozilla {
+namespace a11y {
+
+class ia2AccessibleValue: public IAccessibleValue
+{
+public:
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID, void**);
+
+ // IAccessibleValue
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_currentValue(
+ /* [retval][out] */ VARIANT *currentValue);
+
+ virtual HRESULT STDMETHODCALLTYPE setCurrentValue(
+ /* [in] */ VARIANT value);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_maximumValue(
+ /* [retval][out] */ VARIANT *maximumValue);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_minimumValue(
+ /* [retval][out] */ VARIANT *minimumValue);
+
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/windows/ia2/moz.build b/accessible/windows/ia2/moz.build
new file mode 100644
index 000000000..443e87663
--- /dev/null
+++ b/accessible/windows/ia2/moz.build
@@ -0,0 +1,58 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+EXPORTS += [
+ 'ia2Accessible.h',
+ 'ia2AccessibleAction.h',
+ 'ia2AccessibleComponent.h',
+ 'ia2AccessibleEditableText.h',
+ 'ia2AccessibleHyperlink.h',
+ 'ia2AccessibleHypertext.h',
+ 'ia2AccessibleText.h',
+ 'ia2AccessibleValue.h',
+]
+
+UNIFIED_SOURCES += [
+ 'ia2Accessible.cpp',
+ 'ia2AccessibleAction.cpp',
+ 'ia2AccessibleComponent.cpp',
+ 'ia2AccessibleEditableText.cpp',
+ 'ia2AccessibleHyperlink.cpp',
+ 'ia2AccessibleHypertext.cpp',
+ 'ia2AccessibleImage.cpp',
+ 'ia2AccessibleRelation.cpp',
+ 'ia2AccessibleText.cpp',
+ 'ia2AccessibleValue.cpp',
+]
+
+# These files cannot be built in unified mode because they both include
+# AccessibleTable2_i.c.
+SOURCES += [
+ 'ia2AccessibleTable.cpp',
+ 'ia2AccessibleTableCell.cpp',
+]
+
+LOCAL_INCLUDES += [
+ '/accessible/base',
+ '/accessible/generic',
+ '/accessible/html',
+ '/accessible/windows',
+ '/accessible/windows/msaa',
+ '/accessible/xpcom',
+ '/accessible/xul',
+]
+
+FINAL_LIBRARY = 'xul'
+
+# The Windows MIDL code generator creates things like:
+#
+# #endif !_MIDL_USE_GUIDDEF_
+#
+# which clang-cl complains about. MSVC doesn't, so turn this warning off.
+if CONFIG['CLANG_CL']:
+ CXXFLAGS += ['-Wno-extra-tokens']
+
+include('/ipc/chromium/chromium-config.mozbuild')