mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 922184 - move IAccessible2 implementation into separate class, r=tbsaunde
--HG-- rename : accessible/src/windows/msaa/AccessibleWrap.cpp => accessible/src/windows/ia2/ia2Accessible.cpp rename : accessible/src/windows/msaa/AccessibleWrap.h => accessible/src/windows/ia2/ia2Accessible.h
This commit is contained in:
parent
521b39de48
commit
d516128d55
580
accessible/src/windows/ia2/ia2Accessible.cpp
Normal file
580
accessible/src/windows/ia2/ia2Accessible.cpp
Normal file
@ -0,0 +1,580 @@
|
||||
/* -*- 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 "AccessibleRole.h"
|
||||
#include "AccessibleStates.h"
|
||||
|
||||
#include "Compatibility.h"
|
||||
#include "ia2AccessibleRelation.h"
|
||||
#include "IUnknownImpl.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "nsIAccessibleTypes.h"
|
||||
#include "Relation.h"
|
||||
|
||||
#include "nsIPersistentProperties2.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ia2Accessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
STDMETHODIMP
|
||||
ia2Accessible::QueryInterface(REFIID iid, void** ppv)
|
||||
{
|
||||
if (!ppv)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*ppv = nullptr;
|
||||
|
||||
if (IID_IAccessible2 == iid && !Compatibility::IsIA2Off()) {
|
||||
*ppv = static_cast<IAccessible2*>(this);
|
||||
(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;
|
||||
|
||||
for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2); idx++) {
|
||||
Relation rel = acc->RelationByType(sRelationTypesForIA2[idx]);
|
||||
if (rel.Next())
|
||||
(*aNRelations)++;
|
||||
}
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
ia2Accessible::get_relation(long aRelationIndex,
|
||||
IAccessibleRelation** aRelation)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aRelation)
|
||||
return E_INVALIDARG;
|
||||
*aRelation = nullptr;
|
||||
|
||||
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
|
||||
if (acc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
long relIdx = 0;
|
||||
for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2); idx++) {
|
||||
uint32_t relType = sRelationTypesForIA2[idx];
|
||||
Relation rel = acc->RelationByType(relType);
|
||||
nsRefPtr<ia2AccessibleRelation> ia2Relation =
|
||||
new ia2AccessibleRelation(relType, &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)
|
||||
return E_INVALIDARG;
|
||||
*aNRelations = 0;
|
||||
|
||||
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
|
||||
if (acc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2) &&
|
||||
*aNRelations < aMaxRelations; idx++) {
|
||||
uint32_t relType = sRelationTypesForIA2[idx];
|
||||
Relation rel = acc->RelationByType(relType);
|
||||
nsRefPtr<ia2AccessibleRelation> ia2Rel =
|
||||
new ia2AccessibleRelation(relType, &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 = 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.
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
nsresult rv = acc->ScrollToPoint(geckoCoordType, aX, aY);
|
||||
return GetHRESULT(rv);
|
||||
|
||||
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);
|
||||
uint64_t 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 = - reinterpret_cast<intptr_t>(acc->UniqueID());
|
||||
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;
|
||||
|
||||
*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 ":;=,\".
|
||||
nsCOMPtr<nsIPersistentProperties> attributes = acc->Attributes();
|
||||
return ConvertToIA2Attributes(attributes, aAttributes);
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
|
||||
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;
|
||||
|
||||
const char kCharsToEscape[] = ":;=,\\";
|
||||
|
||||
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;
|
||||
|
||||
int32_t offset = 0;
|
||||
while ((offset = name.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
|
||||
name.Insert('\\', offset);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
nsAutoString value;
|
||||
if (NS_FAILED(propElem->GetValue(value)))
|
||||
return E_FAIL;
|
||||
|
||||
offset = 0;
|
||||
while ((offset = value.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
|
||||
value.Insert('\\', offset);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
99
accessible/src/windows/ia2/ia2Accessible.h
Normal file
99
accessible/src/windows/ia2/ia2Accessible.h
Normal file
@ -0,0 +1,99 @@
|
||||
/* -*- 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.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
class ia2Accessible : public IAccessible2
|
||||
{
|
||||
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);
|
||||
|
||||
|
||||
// Helper method
|
||||
static HRESULT ConvertToIA2Attributes(nsIPersistentProperties* aAttributes,
|
||||
BSTR* aIA2Attributes);
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -7,6 +7,7 @@
|
||||
MODULE = 'accessibility'
|
||||
|
||||
EXPORTS += [
|
||||
'ia2Accessible.h',
|
||||
'ia2AccessibleAction.h',
|
||||
'ia2AccessibleComponent.h',
|
||||
'ia2AccessibleEditableText.h',
|
||||
@ -17,6 +18,7 @@ EXPORTS += [
|
||||
]
|
||||
|
||||
CPP_SOURCES += [
|
||||
'ia2Accessible.cpp',
|
||||
'ia2AccessibleAction.cpp',
|
||||
'ia2AccessibleComponent.cpp',
|
||||
'ia2AccessibleEditableText.cpp',
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* -*- 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/. */
|
||||
@ -9,10 +10,10 @@
|
||||
#include "Compatibility.h"
|
||||
#include "DocAccessible-inl.h"
|
||||
#include "EnumVariant.h"
|
||||
#include "ia2AccessibleRelation.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "nsIAccessibleEvent.h"
|
||||
#include "nsIAccessibleRelation.h"
|
||||
#include "nsWinUtils.h"
|
||||
#include "ServiceProvider.h"
|
||||
#include "Relation.h"
|
||||
@ -38,13 +39,7 @@
|
||||
#include "nsArrayUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#include "Accessible2_i.c"
|
||||
#include "AccessibleRole.h"
|
||||
#include "AccessibleStates.h"
|
||||
#include "oleacc.h"
|
||||
#include "nsIAccessibleTypes.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
@ -96,8 +91,6 @@ AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
|
||||
*ppv = static_cast<IEnumVARIANT*>(new ChildrenEnumVariant(this));
|
||||
} else if (IID_IServiceProvider == iid)
|
||||
*ppv = new ServiceProvider(this);
|
||||
else if (IID_IAccessible2 == iid && !Compatibility::IsIA2Off())
|
||||
*ppv = static_cast<IAccessible2*>(this);
|
||||
else if (IID_ISimpleDOMNode == iid) {
|
||||
if (IsDefunct() || (!HasOwnContent() && !IsDoc()))
|
||||
return E_NOINTERFACE;
|
||||
@ -105,6 +98,12 @@ AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
|
||||
*ppv = static_cast<ISimpleDOMNode*>(new sdnAccessible(GetNode()));
|
||||
}
|
||||
|
||||
if (nullptr == *ppv) {
|
||||
HRESULT hr = ia2Accessible::QueryInterface(iid, ppv);
|
||||
if (SUCCEEDED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (nullptr == *ppv) {
|
||||
HRESULT hr = ia2AccessibleComponent::QueryInterface(iid, ppv);
|
||||
if (SUCCEEDED(hr))
|
||||
@ -1069,468 +1068,6 @@ AccessibleWrap::put_accValue(
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccessibleWrap. IAccessible2
|
||||
|
||||
STDMETHODIMP
|
||||
AccessibleWrap::get_nRelations(long *aNRelations)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aNRelations)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aNRelations = 0;
|
||||
|
||||
if (IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2); idx++) {
|
||||
Relation rel = RelationByType(sRelationTypesForIA2[idx]);
|
||||
if (rel.Next())
|
||||
(*aNRelations)++;
|
||||
}
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
AccessibleWrap::get_relation(long aRelationIndex,
|
||||
IAccessibleRelation** aRelation)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aRelation)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aRelation = nullptr;
|
||||
|
||||
if (IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
long relIdx = 0;
|
||||
for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2); idx++) {
|
||||
uint32_t relType = sRelationTypesForIA2[idx];
|
||||
Relation rel = RelationByType(relType);
|
||||
nsRefPtr<ia2AccessibleRelation> ia2Relation =
|
||||
new ia2AccessibleRelation(relType, &rel);
|
||||
if (ia2Relation->HasTargets()) {
|
||||
if (relIdx == aRelationIndex) {
|
||||
ia2Relation.forget(aRelation);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
relIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
return E_INVALIDARG;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
AccessibleWrap::get_relations(long aMaxRelations,
|
||||
IAccessibleRelation **aRelation,
|
||||
long *aNRelations)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aRelation || !aNRelations)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aNRelations = 0;
|
||||
|
||||
if (IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2) &&
|
||||
*aNRelations < aMaxRelations; idx++) {
|
||||
uint32_t relType = sRelationTypesForIA2[idx];
|
||||
Relation rel = RelationByType(relType);
|
||||
nsRefPtr<ia2AccessibleRelation> ia2Rel =
|
||||
new ia2AccessibleRelation(relType, &rel);
|
||||
if (ia2Rel->HasTargets()) {
|
||||
ia2Rel.forget(aRelation + (*aNRelations));
|
||||
(*aNRelations)++;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
AccessibleWrap::role(long *aRole)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aRole)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aRole = 0;
|
||||
|
||||
if (IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
#define ROLE(_geckoRole, stringRole, atkRole, macRole, \
|
||||
msaaRole, ia2Role, nameRule) \
|
||||
case roles::_geckoRole: \
|
||||
*aRole = ia2Role; \
|
||||
break;
|
||||
|
||||
a11y::role geckoRole = 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.
|
||||
if (geckoRole == roles::ROW) {
|
||||
Accessible* xpParent = Parent();
|
||||
if (xpParent && xpParent->Role() == roles::TREE_TABLE)
|
||||
*aRole = ROLE_SYSTEM_OUTLINEITEM;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
AccessibleWrap::scrollTo(enum IA2ScrollType aScrollType)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
nsCoreUtils::ScrollTo(mDoc->PresShell(), mContent, aScrollType);
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
AccessibleWrap::scrollToPoint(enum IA2CoordinateType aCoordType,
|
||||
long aX, long aY)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
|
||||
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
|
||||
nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
|
||||
|
||||
nsresult rv = ScrollToPoint(geckoCoordType, aX, aY);
|
||||
return GetHRESULT(rv);
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
AccessibleWrap::get_groupPosition(long *aGroupLevel,
|
||||
long *aSimilarItemsInGroup,
|
||||
long *aPositionInGroup)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aGroupLevel || !aSimilarItemsInGroup || !aPositionInGroup)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aGroupLevel = 0;
|
||||
*aSimilarItemsInGroup = 0;
|
||||
*aPositionInGroup = 0;
|
||||
|
||||
if (IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
GroupPos groupPos = 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
|
||||
AccessibleWrap::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.
|
||||
|
||||
uint64_t state = 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
|
||||
AccessibleWrap::get_extendedRole(BSTR *aExtendedRole)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aExtendedRole)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aExtendedRole = nullptr;
|
||||
return E_NOTIMPL;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
AccessibleWrap::get_localizedExtendedRole(BSTR *aLocalizedExtendedRole)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aLocalizedExtendedRole)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aLocalizedExtendedRole = nullptr;
|
||||
return E_NOTIMPL;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
AccessibleWrap::get_nExtendedStates(long *aNExtendedStates)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aNExtendedStates)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aNExtendedStates = 0;
|
||||
return E_NOTIMPL;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
AccessibleWrap::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
|
||||
AccessibleWrap::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
|
||||
AccessibleWrap::get_uniqueID(long *uniqueID)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!uniqueID)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*uniqueID = - reinterpret_cast<intptr_t>(UniqueID());
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
AccessibleWrap::get_windowHandle(HWND *aWindowHandle)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aWindowHandle)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aWindowHandle = 0;
|
||||
|
||||
if (IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
*aWindowHandle = GetHWNDFor(this);
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
AccessibleWrap::get_indexInParent(long *aIndexInParent)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aIndexInParent)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aIndexInParent = -1;
|
||||
if (IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
*aIndexInParent = IndexInParent();
|
||||
if (*aIndexInParent == -1)
|
||||
return S_FALSE;
|
||||
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
AccessibleWrap::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.
|
||||
|
||||
if (IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
nsAutoString lang;
|
||||
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
|
||||
AccessibleWrap::get_attributes(BSTR *aAttributes)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aAttributes)
|
||||
return E_INVALIDARG;
|
||||
|
||||
// The format is name:value;name:value; with \ for escaping these
|
||||
// characters ":;=,\".
|
||||
*aAttributes = nullptr;
|
||||
|
||||
if (IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
nsCOMPtr<nsIPersistentProperties> attributes = Attributes();
|
||||
return ConvertToIA2Attributes(attributes, aAttributes);
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// IDispatch
|
||||
|
||||
@ -1732,69 +1269,6 @@ AccessibleWrap::GetHWNDFor(Accessible* aAccessible)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
AccessibleWrap::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;
|
||||
|
||||
const char kCharsToEscape[] = ":;=,\\";
|
||||
|
||||
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;
|
||||
|
||||
int32_t offset = 0;
|
||||
while ((offset = name.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
|
||||
name.Insert('\\', offset);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
nsAutoString value;
|
||||
if (NS_FAILED(propElem->GetValue(value)))
|
||||
return E_FAIL;
|
||||
|
||||
offset = 0;
|
||||
while ((offset = value.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
|
||||
value.Insert('\\', offset);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
IDispatch*
|
||||
AccessibleWrap::NativeAccessible(nsIAccessible* aAccessible)
|
||||
{
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "Accessible.h"
|
||||
#include "Accessible2.h"
|
||||
#include "ia2Accessible.h"
|
||||
#include "ia2AccessibleComponent.h"
|
||||
#include "ia2AccessibleHyperlink.h"
|
||||
#include "ia2AccessibleValue.h"
|
||||
@ -25,10 +26,10 @@ namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
class AccessibleWrap : public Accessible,
|
||||
public ia2Accessible,
|
||||
public ia2AccessibleComponent,
|
||||
public ia2AccessibleHyperlink,
|
||||
public ia2AccessibleValue,
|
||||
public IAccessible2
|
||||
public ia2AccessibleValue
|
||||
{
|
||||
public: // construction, destruction
|
||||
AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
@ -130,72 +131,6 @@ public: // construction, destruction
|
||||
/* [optional][in] */ VARIANT varChild,
|
||||
/* [in] */ BSTR szValue);
|
||||
|
||||
public: // 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);
|
||||
|
||||
// IDispatch (support of scripting languages like VB)
|
||||
virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo);
|
||||
|
||||
@ -221,8 +156,6 @@ public: // construction, destruction
|
||||
// Helper methods
|
||||
static int32_t GetChildIDFor(Accessible* aAccessible);
|
||||
static HWND GetHWNDFor(Accessible* aAccessible);
|
||||
static HRESULT ConvertToIA2Attributes(nsIPersistentProperties *aAttributes,
|
||||
BSTR *aIA2Attributes);
|
||||
|
||||
/**
|
||||
* System caret support: update the Windows caret position.
|
||||
|
Loading…
Reference in New Issue
Block a user