mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 527461 - Implement RELATION_NODE_PARENT_OF, r=tbsaunde
This commit is contained in:
parent
f79e9a13d1
commit
caaa87b509
@ -10,37 +10,62 @@ interface nsIAccessible;
|
||||
|
||||
/**
|
||||
* This interface gives access to an accessible's set of relations.
|
||||
* Be carefull, do not change constants until ATK has a structure to map gecko
|
||||
* constants into ATK constants.
|
||||
*/
|
||||
[scriptable, uuid(f42a1589-70ab-4704-877f-4a9162bbe188)]
|
||||
[scriptable, uuid(9f85fc0d-2969-48e6-b822-68140f7e5770)]
|
||||
interface nsIAccessibleRelation : nsISupports
|
||||
{
|
||||
|
||||
const unsigned long RELATION_NUL = 0x00;
|
||||
|
||||
/**
|
||||
* Some attribute of this object is affected by a target object.
|
||||
* This object is labelled by a target object.
|
||||
*/
|
||||
const unsigned long RELATION_CONTROLLED_BY = 0x01;
|
||||
|
||||
// First relation
|
||||
const unsigned long RELATION_FIRST = RELATION_CONTROLLED_BY;
|
||||
|
||||
/**
|
||||
* This object is interactive and controls some attribute of a target object.
|
||||
*/
|
||||
const unsigned long RELATION_CONTROLLER_FOR = 0x02;
|
||||
const unsigned long RELATION_LABELLED_BY = 0x00;
|
||||
|
||||
/**
|
||||
* This object is label for a target object.
|
||||
*/
|
||||
const unsigned long RELATION_LABEL_FOR = 0x03;
|
||||
const unsigned long RELATION_LABEL_FOR = 0x01;
|
||||
|
||||
/**
|
||||
* This object is labelled by a target object.
|
||||
* This object is described by the target object.
|
||||
*/
|
||||
const unsigned long RELATION_LABELLED_BY = 0x04;
|
||||
const unsigned long RELATION_DESCRIBED_BY = 0x02;
|
||||
|
||||
/**
|
||||
* This object is describes the target object.
|
||||
*/
|
||||
const unsigned long RELATION_DESCRIPTION_FOR = 0x3;
|
||||
|
||||
/**
|
||||
* This object is a child of a target object.
|
||||
*/
|
||||
const unsigned long RELATION_NODE_CHILD_OF = 0x4;
|
||||
|
||||
/**
|
||||
* This object is a parent of a target object. A dual relation to
|
||||
* RELATION_NODE_CHILD_OF
|
||||
*/
|
||||
const unsigned long RELATION_NODE_PARENT_OF = 0x5;
|
||||
|
||||
/**
|
||||
* Some attribute of this object is affected by a target object.
|
||||
*/
|
||||
const unsigned long RELATION_CONTROLLED_BY = 0x06;
|
||||
|
||||
/**
|
||||
* This object is interactive and controls some attribute of a target object.
|
||||
*/
|
||||
const unsigned long RELATION_CONTROLLER_FOR = 0x07;
|
||||
|
||||
/**
|
||||
* Content flows from this object to a target object, i.e. has content that
|
||||
* flows logically to another object in a sequential way, e.g. text flow.
|
||||
*/
|
||||
const unsigned long RELATION_FLOWS_TO = 0x08;
|
||||
|
||||
/**
|
||||
* Content flows to this object from a target object, i.e. has content that
|
||||
* flows logically from another object in a sequential way, e.g. text flow.
|
||||
*/
|
||||
const unsigned long RELATION_FLOWS_FROM = 0x09;
|
||||
|
||||
/**
|
||||
* This object is a member of a group of one or more objects. When there is
|
||||
@ -48,71 +73,41 @@ interface nsIAccessibleRelation : nsISupports
|
||||
* target, e.g. a grouping object. It is also possible that each member has
|
||||
* multiple additional targets, e.g. one for every other member in the group.
|
||||
*/
|
||||
const unsigned long RELATION_MEMBER_OF = 0x05;
|
||||
|
||||
/**
|
||||
* This object is a child of a target object.
|
||||
*/
|
||||
const unsigned long RELATION_NODE_CHILD_OF = 0x06;
|
||||
|
||||
/**
|
||||
* Content flows from this object to a target object, i.e. has content that
|
||||
* flows logically to another object in a sequential way, e.g. text flow.
|
||||
*/
|
||||
const unsigned long RELATION_FLOWS_TO = 0x07;
|
||||
|
||||
/**
|
||||
* Content flows to this object from a target object, i.e. has content that
|
||||
* flows logically from another object in a sequential way, e.g. text flow.
|
||||
*/
|
||||
const unsigned long RELATION_FLOWS_FROM = 0x08;
|
||||
const unsigned long RELATION_MEMBER_OF = 0x0a;
|
||||
|
||||
/**
|
||||
* This object is a sub window of a target object.
|
||||
*/
|
||||
const unsigned long RELATION_SUBWINDOW_OF = 0x09;
|
||||
const unsigned long RELATION_SUBWINDOW_OF = 0x0b;
|
||||
|
||||
/**
|
||||
* This object embeds a target object. This relation can be used on the
|
||||
* OBJID_CLIENT accessible for a top level window to show where the content
|
||||
* areas are.
|
||||
*/
|
||||
const unsigned long RELATION_EMBEDS = 0x0a;
|
||||
const unsigned long RELATION_EMBEDS = 0x0c;
|
||||
|
||||
/**
|
||||
* This object is embedded by a target object.
|
||||
*/
|
||||
const unsigned long RELATION_EMBEDDED_BY = 0x0b;
|
||||
const unsigned long RELATION_EMBEDDED_BY = 0x0d;
|
||||
|
||||
/**
|
||||
* This object is a transient component related to the target object. When
|
||||
* this object is activated the target object doesn't lose focus.
|
||||
*/
|
||||
const unsigned long RELATION_POPUP_FOR = 0x0c;
|
||||
const unsigned long RELATION_POPUP_FOR = 0x0e;
|
||||
|
||||
/**
|
||||
* This object is a parent window of the target object.
|
||||
*/
|
||||
const unsigned long RELATION_PARENT_WINDOW_OF = 0x0d;
|
||||
|
||||
/**
|
||||
* This object is described by the target object.
|
||||
*/
|
||||
const unsigned long RELATION_DESCRIBED_BY = 0x0e;
|
||||
|
||||
/**
|
||||
* This object is describes the target object.
|
||||
*/
|
||||
const unsigned long RELATION_DESCRIPTION_FOR = 0x0f;
|
||||
|
||||
// Last relation that is standard to desktop accessibility APIs
|
||||
const unsigned long RELATION_LAST = RELATION_DESCRIPTION_FOR;
|
||||
const unsigned long RELATION_PARENT_WINDOW_OF = 0x0f;
|
||||
|
||||
/**
|
||||
* Part of a form/dialog with a related default button. It is used for
|
||||
* MSAA only, no for IA2 nor ATK.
|
||||
* MSAA/XPCOM, it isn't for IA2 or ATK.
|
||||
*/
|
||||
const unsigned long RELATION_DEFAULT_BUTTON = 0x4000;
|
||||
const unsigned long RELATION_DEFAULT_BUTTON = 0x10;
|
||||
|
||||
/**
|
||||
* Returns the type of the relation.
|
||||
|
@ -853,21 +853,29 @@ refRelationSetCB(AtkObject *aAtkObj)
|
||||
if (!accWrap)
|
||||
return relation_set;
|
||||
|
||||
uint32_t relationTypes[] = {
|
||||
nsIAccessibleRelation::RELATION_LABELLED_BY,
|
||||
nsIAccessibleRelation::RELATION_LABEL_FOR,
|
||||
nsIAccessibleRelation::RELATION_NODE_CHILD_OF,
|
||||
// Keep in sync with AtkRelationType enum.
|
||||
static const uint32_t relationTypes[] = {
|
||||
nsIAccessibleRelation::RELATION_CONTROLLED_BY,
|
||||
nsIAccessibleRelation::RELATION_CONTROLLER_FOR,
|
||||
nsIAccessibleRelation::RELATION_EMBEDS,
|
||||
nsIAccessibleRelation::RELATION_LABEL_FOR,
|
||||
nsIAccessibleRelation::RELATION_LABELLED_BY,
|
||||
nsIAccessibleRelation::RELATION_MEMBER_OF,
|
||||
nsIAccessibleRelation::RELATION_NODE_CHILD_OF,
|
||||
nsIAccessibleRelation::RELATION_FLOWS_TO,
|
||||
nsIAccessibleRelation::RELATION_FLOWS_FROM,
|
||||
nsIAccessibleRelation::RELATION_SUBWINDOW_OF,
|
||||
nsIAccessibleRelation::RELATION_EMBEDS,
|
||||
nsIAccessibleRelation::RELATION_EMBEDDED_BY,
|
||||
nsIAccessibleRelation::RELATION_POPUP_FOR,
|
||||
nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF,
|
||||
nsIAccessibleRelation::RELATION_DESCRIBED_BY,
|
||||
nsIAccessibleRelation::RELATION_DESCRIPTION_FOR,
|
||||
nsIAccessibleRelation::RELATION_NODE_PARENT_OF
|
||||
};
|
||||
|
||||
for (uint32_t i = 0; i < ArrayLength(relationTypes); i++) {
|
||||
AtkRelationType atkType = static_cast<AtkRelationType>(relationTypes[i]);
|
||||
// Shift to 1 to skip ATK_RELATION_NULL.
|
||||
AtkRelationType atkType = static_cast<AtkRelationType>(i + 1);
|
||||
AtkRelation* atkRelation =
|
||||
atk_relation_set_get_relation_by_type(relation_set, atkType);
|
||||
if (atkRelation)
|
||||
|
@ -138,6 +138,55 @@ AccGroupInfo::AccGroupInfo(Accessible* aItem, role aRole) :
|
||||
mParent = parentPrevSibling;
|
||||
}
|
||||
|
||||
Accessible*
|
||||
AccGroupInfo::FirstItemOf(Accessible* aContainer)
|
||||
{
|
||||
// ARIA trees can be arranged by ARIA groups, otherwise aria-level works.
|
||||
a11y::role containerRole = aContainer->Role();
|
||||
Accessible* item = aContainer->NextSibling();
|
||||
if (item) {
|
||||
if (containerRole == roles::OUTLINEITEM && item->Role() == roles::GROUPING)
|
||||
item = item->FirstChild();
|
||||
|
||||
AccGroupInfo* itemGroupInfo = item->GetGroupInfo();
|
||||
if (itemGroupInfo && itemGroupInfo->ConceptualParent() == aContainer)
|
||||
return item;
|
||||
}
|
||||
|
||||
// Otherwise it can be a direct child.
|
||||
item = aContainer->FirstChild();
|
||||
if (item && IsConceptualParent(BaseRole(item->Role()), containerRole))
|
||||
return item;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Accessible*
|
||||
AccGroupInfo::NextItemTo(Accessible* aItem)
|
||||
{
|
||||
AccGroupInfo* groupInfo = aItem->GetGroupInfo();
|
||||
if (!groupInfo)
|
||||
return nullptr;
|
||||
|
||||
// If the item in middle of the group then search next item in siblings.
|
||||
if (groupInfo->PosInSet() >= groupInfo->SetSize())
|
||||
return nullptr;
|
||||
|
||||
Accessible* parent = aItem->Parent();
|
||||
uint32_t childCount = parent->ChildCount();
|
||||
for (int32_t idx = aItem->IndexInParent() + 1; idx < childCount; idx++) {
|
||||
Accessible* nextItem = parent->GetChildAt(idx);
|
||||
AccGroupInfo* nextGroupInfo = nextItem->GetGroupInfo();
|
||||
if (nextGroupInfo &&
|
||||
nextGroupInfo->ConceptualParent() == groupInfo->ConceptualParent()) {
|
||||
return nextItem;
|
||||
}
|
||||
}
|
||||
|
||||
NS_NOTREACHED("Item in the midle of the group but there's no next item!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
AccGroupInfo::IsConceptualParent(role aRole, role aParentRole)
|
||||
{
|
||||
|
@ -17,11 +17,22 @@ namespace a11y {
|
||||
class AccGroupInfo
|
||||
{
|
||||
public:
|
||||
AccGroupInfo(Accessible* aItem, mozilla::a11y::role aRole);
|
||||
~AccGroupInfo() { MOZ_COUNT_DTOR(AccGroupInfo); }
|
||||
|
||||
int32_t PosInSet() const { return mPosInSet; }
|
||||
/**
|
||||
* Return 1-based position in the group.
|
||||
*/
|
||||
uint32_t PosInSet() const { return mPosInSet; }
|
||||
|
||||
/**
|
||||
* Return a number of items in the group.
|
||||
*/
|
||||
uint32_t SetSize() const { return mSetSize; }
|
||||
|
||||
/**
|
||||
* Return a direct or logical parent of the accessible that this group info is
|
||||
* created for.
|
||||
*/
|
||||
Accessible* ConceptualParent() const { return mParent; }
|
||||
|
||||
/**
|
||||
@ -50,9 +61,23 @@ public:
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a first item for the given container.
|
||||
*/
|
||||
static Accessible* FirstItemOf(Accessible* aContainer);
|
||||
|
||||
/**
|
||||
* Return next item of the same group to the given item.
|
||||
*/
|
||||
static Accessible* NextItemTo(Accessible* aItem);
|
||||
|
||||
protected:
|
||||
AccGroupInfo(Accessible* aItem, a11y::role aRole);
|
||||
|
||||
private:
|
||||
AccGroupInfo(const AccGroupInfo&);
|
||||
AccGroupInfo& operator =(const AccGroupInfo&);
|
||||
AccGroupInfo() MOZ_DELETE;
|
||||
AccGroupInfo(const AccGroupInfo&) MOZ_DELETE;
|
||||
AccGroupInfo& operator =(const AccGroupInfo&) MOZ_DELETE;
|
||||
|
||||
static mozilla::a11y::role BaseRole(mozilla::a11y::role aRole)
|
||||
{
|
||||
@ -71,8 +96,7 @@ private:
|
||||
* Return true if the given parent role is conceptual parent of the given
|
||||
* role.
|
||||
*/
|
||||
static bool IsConceptualParent(mozilla::a11y::role aRole,
|
||||
mozilla::a11y::role aParentRole);
|
||||
static bool IsConceptualParent(a11y::role aRole, a11y::role aParentRole);
|
||||
|
||||
uint32_t mPosInSet;
|
||||
uint32_t mSetSize;
|
||||
|
@ -5,7 +5,11 @@
|
||||
#include "AccIterator.h"
|
||||
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "AccGroupInfo.h"
|
||||
#include "Accessible-inl.h"
|
||||
#ifdef MOZ_XUL
|
||||
#include "XULTreeAccessible.h"
|
||||
#endif
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsBindingManager.h"
|
||||
@ -329,6 +333,11 @@ IDRefsIterator::Next()
|
||||
return nextElm ? mDoc->GetAccessible(nextElm) : nullptr;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SingleAccIterator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Accessible*
|
||||
SingleAccIterator::Next()
|
||||
{
|
||||
@ -337,3 +346,56 @@ SingleAccIterator::Next()
|
||||
return (nextAcc && !nextAcc->IsDefunct()) ? nextAcc : nullptr;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ItemIterator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Accessible*
|
||||
ItemIterator::Next()
|
||||
{
|
||||
if (mContainer) {
|
||||
mAnchor = AccGroupInfo::FirstItemOf(mContainer);
|
||||
mContainer = nullptr;
|
||||
return mAnchor;
|
||||
}
|
||||
|
||||
return mAnchor ? (mAnchor = AccGroupInfo::NextItemTo(mAnchor)) : nullptr;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// XULTreeItemIterator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
XULTreeItemIterator::XULTreeItemIterator(XULTreeAccessible* aXULTree,
|
||||
nsITreeView* aTreeView,
|
||||
int32_t aRowIdx) :
|
||||
mXULTree(aXULTree), mTreeView(aTreeView), mRowCount(-1),
|
||||
mContainerLevel(-1), mCurrRowIdx(aRowIdx + 1)
|
||||
{
|
||||
mTreeView->GetRowCount(&mRowCount);
|
||||
if (aRowIdx != -1)
|
||||
mTreeView->GetLevel(aRowIdx, &mContainerLevel);
|
||||
}
|
||||
|
||||
Accessible*
|
||||
XULTreeItemIterator::Next()
|
||||
{
|
||||
while (mCurrRowIdx < mRowCount) {
|
||||
int32_t level = 0;
|
||||
mTreeView->GetLevel(mCurrRowIdx, &level);
|
||||
|
||||
if (level == mContainerLevel + 1)
|
||||
return mXULTree->GetTreeItemAccessible(mCurrRowIdx++);
|
||||
|
||||
if (level <= mContainerLevel) { // got level up
|
||||
mCurrRowIdx = mRowCount;
|
||||
break;
|
||||
}
|
||||
|
||||
mCurrRowIdx++;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -266,6 +266,53 @@ private:
|
||||
nsRefPtr<Accessible> mAcc;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Used to iterate items of the given item container.
|
||||
*/
|
||||
class ItemIterator : public AccIterable
|
||||
{
|
||||
public:
|
||||
ItemIterator(Accessible* aItemContainer) :
|
||||
mContainer(aItemContainer), mAnchor(nullptr) { }
|
||||
virtual ~ItemIterator() { }
|
||||
|
||||
virtual Accessible* Next();
|
||||
|
||||
private:
|
||||
ItemIterator() MOZ_DELETE;
|
||||
ItemIterator(const ItemIterator&) MOZ_DELETE;
|
||||
ItemIterator& operator = (const ItemIterator&) MOZ_DELETE;
|
||||
|
||||
Accessible* mContainer;
|
||||
Accessible* mAnchor;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Used to iterate through XUL tree items of the same level.
|
||||
*/
|
||||
class XULTreeItemIterator : public AccIterable
|
||||
{
|
||||
public:
|
||||
XULTreeItemIterator(XULTreeAccessible* aXULTree, nsITreeView* aTreeView,
|
||||
int32_t aRowIdx);
|
||||
virtual ~XULTreeItemIterator() { }
|
||||
|
||||
virtual Accessible* Next();
|
||||
|
||||
private:
|
||||
XULTreeItemIterator() MOZ_DELETE;
|
||||
XULTreeItemIterator(const XULTreeItemIterator&) MOZ_DELETE;
|
||||
XULTreeItemIterator& operator = (const XULTreeItemIterator&) MOZ_DELETE;
|
||||
|
||||
XULTreeAccessible* mXULTree;
|
||||
nsITreeView* mTreeView;
|
||||
int32_t mRowCount;
|
||||
int32_t mContainerLevel;
|
||||
int32_t mCurrRowIdx;
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -19,12 +19,11 @@ namespace a11y {
|
||||
*/
|
||||
struct RelationCopyHelper
|
||||
{
|
||||
RelationCopyHelper(mozilla::a11y::AccIterable* aFirstIter,
|
||||
mozilla::a11y::AccIterable* aLastIter) :
|
||||
RelationCopyHelper(AccIterable* aFirstIter, AccIterable* aLastIter) :
|
||||
mFirstIter(aFirstIter), mLastIter(aLastIter) { }
|
||||
|
||||
mozilla::a11y::AccIterable* mFirstIter;
|
||||
mozilla::a11y::AccIterable* mLastIter;
|
||||
AccIterable* mFirstIter;
|
||||
AccIterable* mLastIter;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -39,7 +38,7 @@ public:
|
||||
Relation(const RelationCopyHelper aRelation) :
|
||||
mFirstIter(aRelation.mFirstIter), mLastIter(aRelation.mLastIter) { }
|
||||
|
||||
Relation(mozilla::a11y::AccIterable* aIter) :
|
||||
Relation(AccIterable* aIter) :
|
||||
mFirstIter(aIter), mLastIter(aIter) { }
|
||||
|
||||
Relation(Accessible* aAcc) :
|
||||
@ -69,7 +68,7 @@ public:
|
||||
return RelationCopyHelper(mFirstIter.forget(), mLastIter);
|
||||
}
|
||||
|
||||
inline void AppendIter(mozilla::a11y::AccIterable* aIter)
|
||||
inline void AppendIter(AccIterable* aIter)
|
||||
{
|
||||
if (mLastIter)
|
||||
mLastIter->mNextIter = aIter;
|
||||
@ -85,7 +84,7 @@ public:
|
||||
inline void AppendTarget(Accessible* aAcc)
|
||||
{
|
||||
if (aAcc)
|
||||
AppendIter(new mozilla::a11y::SingleAccIterator(aAcc));
|
||||
AppendIter(new SingleAccIterator(aAcc));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,8 +117,8 @@ public:
|
||||
private:
|
||||
Relation& operator = (const Relation&);
|
||||
|
||||
nsAutoPtr<mozilla::a11y::AccIterable> mFirstIter;
|
||||
mozilla::a11y::AccIterable* mLastIter;
|
||||
nsAutoPtr<AccIterable> mFirstIter;
|
||||
AccIterable* mLastIter;
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
|
@ -587,9 +587,8 @@ enum Role {
|
||||
TOGGLE_BUTTON = 93,
|
||||
|
||||
/**
|
||||
* Representas a control that is capable of expanding and collapsing rows as
|
||||
* Represent a control that is capable of expanding and collapsing rows as
|
||||
* well as showing multiple columns of data.
|
||||
* XXX: it looks like this role is dupe of OUTLINE.
|
||||
*/
|
||||
TREE_TABLE = 94,
|
||||
|
||||
|
@ -318,22 +318,22 @@ static const char kEventTypeNames[][40] = {
|
||||
* nsIAccessibleRetrieval::getStringRelationType() method.
|
||||
*/
|
||||
static const char kRelationTypeNames[][20] = {
|
||||
"unknown", // RELATION_NUL
|
||||
"labelled by", // RELATION_LABELLED_BY
|
||||
"label for", // RELATION_LABEL_FOR
|
||||
"described by", // RELATION_DESCRIBED_BY
|
||||
"description for", // RELATION_DESCRIPTION_FOR
|
||||
"node child of", // RELATION_NODE_CHILD_OF
|
||||
"node parent of", // RELATION_NODE_PARENT_OF
|
||||
"controlled by", // RELATION_CONTROLLED_BY
|
||||
"controller for", // RELATION_CONTROLLER_FOR
|
||||
"label for", // RELATION_LABEL_FOR
|
||||
"labelled by", // RELATION_LABELLED_BY
|
||||
"member of", // RELATION_MEMBER_OF
|
||||
"node child of", // RELATION_NODE_CHILD_OF
|
||||
"flows to", // RELATION_FLOWS_TO
|
||||
"flows from", // RELATION_FLOWS_FROM
|
||||
"member of", // RELATION_MEMBER_OF
|
||||
"subwindow of", // RELATION_SUBWINDOW_OF
|
||||
"embeds", // RELATION_EMBEDS
|
||||
"embedded by", // RELATION_EMBEDDED_BY
|
||||
"popup for", // RELATION_POPUP_FOR
|
||||
"parent window of", // RELATION_PARENT_WINDOW_OF
|
||||
"described by", // RELATION_DESCRIBED_BY
|
||||
"description for", // RELATION_DESCRIPTION_FOR
|
||||
"default button" // RELATION_DEFAULT_BUTTON
|
||||
};
|
||||
|
||||
|
@ -1967,16 +1967,6 @@ Accessible::RelationByType(uint32_t aType)
|
||||
// Relationships are defined on the same content node that the role would be
|
||||
// defined on.
|
||||
switch (aType) {
|
||||
case nsIAccessibleRelation::RELATION_LABEL_FOR: {
|
||||
Relation rel(new RelatedAccIterator(Document(), mContent,
|
||||
nsGkAtoms::aria_labelledby));
|
||||
if (mContent->Tag() == nsGkAtoms::label)
|
||||
rel.AppendIter(new IDRefsIterator(mDoc, mContent, mContent->IsHTML() ?
|
||||
nsGkAtoms::_for :
|
||||
nsGkAtoms::control));
|
||||
|
||||
return rel;
|
||||
}
|
||||
case nsIAccessibleRelation::RELATION_LABELLED_BY: {
|
||||
Relation rel(new IDRefsIterator(mDoc, mContent,
|
||||
nsGkAtoms::aria_labelledby));
|
||||
@ -1988,6 +1978,18 @@ Accessible::RelationByType(uint32_t aType)
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_LABEL_FOR: {
|
||||
Relation rel(new RelatedAccIterator(Document(), mContent,
|
||||
nsGkAtoms::aria_labelledby));
|
||||
if (mContent->Tag() == nsGkAtoms::label)
|
||||
rel.AppendIter(new IDRefsIterator(mDoc, mContent, mContent->IsHTML() ?
|
||||
nsGkAtoms::_for :
|
||||
nsGkAtoms::control));
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_DESCRIBED_BY: {
|
||||
Relation rel(new IDRefsIterator(mDoc, mContent,
|
||||
nsGkAtoms::aria_describedby));
|
||||
@ -1996,6 +1998,7 @@ Accessible::RelationByType(uint32_t aType)
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_DESCRIPTION_FOR: {
|
||||
Relation rel(new RelatedAccIterator(Document(), mContent,
|
||||
nsGkAtoms::aria_describedby));
|
||||
@ -2010,19 +2013,16 @@ Accessible::RelationByType(uint32_t aType)
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_NODE_CHILD_OF: {
|
||||
Relation rel(new RelatedAccIterator(Document(), mContent,
|
||||
nsGkAtoms::aria_owns));
|
||||
|
||||
|
||||
// This is an ARIA tree or treegrid that doesn't use owns, so we need to
|
||||
// get the parent the hard way.
|
||||
if (mRoleMapEntry && (mRoleMapEntry->role == roles::OUTLINEITEM ||
|
||||
mRoleMapEntry->role == roles::ROW)) {
|
||||
AccGroupInfo* groupInfo = GetGroupInfo();
|
||||
if (!groupInfo)
|
||||
return rel;
|
||||
|
||||
rel.AppendTarget(groupInfo->ConceptualParent());
|
||||
rel.AppendTarget(GetGroupInfo()->ConceptualParent());
|
||||
}
|
||||
|
||||
// If accessible is in its own Window, or is the root of a document,
|
||||
@ -2043,21 +2043,52 @@ Accessible::RelationByType(uint32_t aType)
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_NODE_PARENT_OF: {
|
||||
Relation rel(new IDRefsIterator(mDoc, mContent, nsGkAtoms::aria_owns));
|
||||
|
||||
// ARIA tree or treegrid can do the hierarchy by @aria-level, ARIA trees
|
||||
// also can be organized by groups.
|
||||
if (mRoleMapEntry &&
|
||||
(mRoleMapEntry->role == roles::OUTLINEITEM ||
|
||||
mRoleMapEntry->role == roles::ROW ||
|
||||
mRoleMapEntry->role == roles::OUTLINE ||
|
||||
mRoleMapEntry->role == roles::TREE_TABLE)) {
|
||||
rel.AppendIter(new ItemIterator(this));
|
||||
}
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_CONTROLLED_BY:
|
||||
return Relation(new RelatedAccIterator(Document(), mContent,
|
||||
nsGkAtoms::aria_controls));
|
||||
|
||||
case nsIAccessibleRelation::RELATION_CONTROLLER_FOR: {
|
||||
Relation rel(new IDRefsIterator(mDoc, mContent,
|
||||
nsGkAtoms::aria_controls));
|
||||
rel.AppendIter(new HTMLOutputIterator(Document(), mContent));
|
||||
return rel;
|
||||
}
|
||||
|
||||
case nsIAccessibleRelation::RELATION_FLOWS_TO:
|
||||
return Relation(new IDRefsIterator(mDoc, mContent,
|
||||
nsGkAtoms::aria_flowto));
|
||||
|
||||
case nsIAccessibleRelation::RELATION_FLOWS_FROM:
|
||||
return Relation(new RelatedAccIterator(Document(), mContent,
|
||||
nsGkAtoms::aria_flowto));
|
||||
|
||||
case nsIAccessibleRelation::RELATION_MEMBER_OF:
|
||||
return Relation(mDoc, GetAtomicRegion());
|
||||
|
||||
case nsIAccessibleRelation::RELATION_SUBWINDOW_OF:
|
||||
case nsIAccessibleRelation::RELATION_EMBEDS:
|
||||
case nsIAccessibleRelation::RELATION_EMBEDDED_BY:
|
||||
case nsIAccessibleRelation::RELATION_POPUP_FOR:
|
||||
case nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF:
|
||||
return Relation();
|
||||
|
||||
case nsIAccessibleRelation::RELATION_DEFAULT_BUTTON: {
|
||||
if (mContent->IsHTML()) {
|
||||
// HTML form controls implements nsIFormControl interface.
|
||||
@ -2105,15 +2136,9 @@ Accessible::RelationByType(uint32_t aType)
|
||||
}
|
||||
return Relation();
|
||||
}
|
||||
case nsIAccessibleRelation::RELATION_MEMBER_OF:
|
||||
return Relation(mDoc, GetAtomicRegion());
|
||||
case nsIAccessibleRelation::RELATION_SUBWINDOW_OF:
|
||||
case nsIAccessibleRelation::RELATION_EMBEDS:
|
||||
case nsIAccessibleRelation::RELATION_EMBEDDED_BY:
|
||||
case nsIAccessibleRelation::RELATION_POPUP_FOR:
|
||||
case nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF:
|
||||
|
||||
default:
|
||||
return Relation();
|
||||
return Relation();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2129,12 +2154,29 @@ Accessible::GetRelations(nsIArray **aRelations)
|
||||
nsCOMPtr<nsIMutableArray> relations = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
NS_ENSURE_TRUE(relations, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
for (uint32_t relType = nsIAccessibleRelation::RELATION_FIRST;
|
||||
relType < nsIAccessibleRelation::RELATION_LAST;
|
||||
++relType) {
|
||||
static const uint32_t relationTypes[] = {
|
||||
nsIAccessibleRelation::RELATION_LABELLED_BY,
|
||||
nsIAccessibleRelation::RELATION_LABEL_FOR,
|
||||
nsIAccessibleRelation::RELATION_DESCRIBED_BY,
|
||||
nsIAccessibleRelation::RELATION_DESCRIPTION_FOR,
|
||||
nsIAccessibleRelation::RELATION_NODE_CHILD_OF,
|
||||
nsIAccessibleRelation::RELATION_NODE_PARENT_OF,
|
||||
nsIAccessibleRelation::RELATION_CONTROLLED_BY,
|
||||
nsIAccessibleRelation::RELATION_CONTROLLER_FOR,
|
||||
nsIAccessibleRelation::RELATION_FLOWS_TO,
|
||||
nsIAccessibleRelation::RELATION_FLOWS_FROM,
|
||||
nsIAccessibleRelation::RELATION_MEMBER_OF,
|
||||
nsIAccessibleRelation::RELATION_SUBWINDOW_OF,
|
||||
nsIAccessibleRelation::RELATION_EMBEDS,
|
||||
nsIAccessibleRelation::RELATION_EMBEDDED_BY,
|
||||
nsIAccessibleRelation::RELATION_POPUP_FOR,
|
||||
nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF,
|
||||
nsIAccessibleRelation::RELATION_DEFAULT_BUTTON
|
||||
};
|
||||
|
||||
for (uint32_t idx = 0; idx < ArrayLength(relationTypes); idx++) {
|
||||
nsCOMPtr<nsIAccessibleRelation> relation;
|
||||
nsresult rv = GetRelationByType(relType, getter_AddRefs(relation));
|
||||
nsresult rv = GetRelationByType(relationTypes[idx], getter_AddRefs(relation));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && relation) {
|
||||
uint32_t targets = 0;
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "nsIAccessibleEvent.h"
|
||||
#include "nsIAccessibleRelation.h"
|
||||
#include "nsWinUtils.h"
|
||||
#include "ServiceProvider.h"
|
||||
#include "Relation.h"
|
||||
@ -1048,9 +1047,8 @@ AccessibleWrap::get_nRelations(long *aNRelations)
|
||||
if (IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
for (uint32_t relType = nsIAccessibleRelation::RELATION_FIRST;
|
||||
relType <= nsIAccessibleRelation::RELATION_LAST; relType++) {
|
||||
Relation rel = RelationByType(relType);
|
||||
for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2); idx++) {
|
||||
Relation rel = RelationByType(sRelationTypesForIA2[idx]);
|
||||
if (rel.Next())
|
||||
(*aNRelations)++;
|
||||
}
|
||||
@ -1074,8 +1072,8 @@ AccessibleWrap::get_relation(long aRelationIndex,
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
long relIdx = 0;
|
||||
for (uint32_t relType = nsIAccessibleRelation::RELATION_FIRST;
|
||||
relType <= nsIAccessibleRelation::RELATION_LAST; relType++) {
|
||||
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);
|
||||
@ -1109,9 +1107,9 @@ AccessibleWrap::get_relations(long aMaxRelations,
|
||||
if (IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
for (uint32_t relType = nsIAccessibleRelation::RELATION_FIRST;
|
||||
relType <= nsIAccessibleRelation::RELATION_LAST &&
|
||||
*aNRelations < aMaxRelations; relType++) {
|
||||
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);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define _NS_ACCESSIBLE_RELATION_WRAP_H
|
||||
|
||||
#include "Accessible.h"
|
||||
#include "nsIAccessibleRelation.h"
|
||||
|
||||
#include "nsTArray.h"
|
||||
|
||||
@ -60,6 +61,28 @@ private:
|
||||
ULONG mReferences;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Relations exposed to IAccessible2.
|
||||
*/
|
||||
static const uint32_t sRelationTypesForIA2[] = {
|
||||
nsIAccessibleRelation::RELATION_LABELLED_BY,
|
||||
nsIAccessibleRelation::RELATION_LABEL_FOR,
|
||||
nsIAccessibleRelation::RELATION_DESCRIBED_BY,
|
||||
nsIAccessibleRelation::RELATION_DESCRIPTION_FOR,
|
||||
nsIAccessibleRelation::RELATION_NODE_CHILD_OF,
|
||||
nsIAccessibleRelation::RELATION_CONTROLLED_BY,
|
||||
nsIAccessibleRelation::RELATION_CONTROLLER_FOR,
|
||||
nsIAccessibleRelation::RELATION_FLOWS_TO,
|
||||
nsIAccessibleRelation::RELATION_FLOWS_FROM,
|
||||
nsIAccessibleRelation::RELATION_MEMBER_OF,
|
||||
nsIAccessibleRelation::RELATION_SUBWINDOW_OF,
|
||||
nsIAccessibleRelation::RELATION_EMBEDS,
|
||||
nsIAccessibleRelation::RELATION_EMBEDDED_BY,
|
||||
nsIAccessibleRelation::RELATION_POPUP_FOR,
|
||||
nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -437,6 +437,19 @@ XULTreeAccessible::ChildCount() const
|
||||
return childCount;
|
||||
}
|
||||
|
||||
Relation
|
||||
XULTreeAccessible::RelationByType(uint32_t aType)
|
||||
{
|
||||
if (aType == nsIAccessibleRelation::RELATION_NODE_PARENT_OF) {
|
||||
if (mTreeView)
|
||||
return Relation(new XULTreeItemIterator(this, mTreeView, -1));
|
||||
|
||||
return Relation();
|
||||
}
|
||||
|
||||
return Accessible::RelationByType(aType);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// XULTreeAccessible: Widgets
|
||||
|
||||
@ -798,18 +811,34 @@ XULTreeItemAccessibleBase::RelationByType(uint32_t aType)
|
||||
if (!mTreeView)
|
||||
return Relation();
|
||||
|
||||
if (aType != nsIAccessibleRelation::RELATION_NODE_CHILD_OF)
|
||||
return Relation();
|
||||
switch (aType) {
|
||||
case nsIAccessibleRelation::RELATION_NODE_CHILD_OF: {
|
||||
int32_t parentIndex = -1;
|
||||
if (!NS_SUCCEEDED(mTreeView->GetParentIndex(mRow, &parentIndex)))
|
||||
return Relation();
|
||||
|
||||
int32_t parentIndex = -1;
|
||||
if (!NS_SUCCEEDED(mTreeView->GetParentIndex(mRow, &parentIndex)))
|
||||
return Relation();
|
||||
if (parentIndex == -1)
|
||||
return Relation(mParent);
|
||||
|
||||
if (parentIndex == -1)
|
||||
return Relation(mParent);
|
||||
XULTreeAccessible* treeAcc = mParent->AsXULTree();
|
||||
return Relation(treeAcc->GetTreeItemAccessible(parentIndex));
|
||||
}
|
||||
|
||||
XULTreeAccessible* treeAcc = mParent->AsXULTree();
|
||||
return Relation(treeAcc->GetTreeItemAccessible(parentIndex));
|
||||
case nsIAccessibleRelation::RELATION_NODE_PARENT_OF: {
|
||||
bool isTrue = false;
|
||||
if (NS_FAILED(mTreeView->IsContainerEmpty(mRow, &isTrue)) || isTrue)
|
||||
return Relation();
|
||||
|
||||
if (NS_FAILED(mTreeView->IsContainerOpen(mRow, &isTrue)) || !isTrue)
|
||||
return Relation();
|
||||
|
||||
XULTreeAccessible* tree = mParent->AsXULTree();
|
||||
return Relation(new XULTreeItemIterator(tree, mTreeView, mRow));
|
||||
}
|
||||
|
||||
default:
|
||||
return Relation();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
|
@ -47,6 +47,7 @@ public:
|
||||
|
||||
virtual Accessible* GetChildAt(uint32_t aIndex);
|
||||
virtual uint32_t ChildCount() const;
|
||||
virtual Relation RelationByType(uint32_t aType);
|
||||
|
||||
// SelectAccessible
|
||||
virtual already_AddRefed<nsIArray> SelectedItems();
|
||||
|
@ -610,6 +610,17 @@ function getTextFromClipboard()
|
||||
*/
|
||||
function prettyName(aIdentifier)
|
||||
{
|
||||
if (aIdentifier instanceof Array) {
|
||||
var msg = "";
|
||||
for (var idx = 0; idx < aIdentifier.length; idx++) {
|
||||
if (msg != "")
|
||||
msg += ", ";
|
||||
|
||||
msg += prettyName(aIdentifier[idx]);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
if (aIdentifier instanceof nsIAccessible) {
|
||||
var acc = getAccessible(aIdentifier);
|
||||
var msg = "[" + getNodePrettyName(acc.DOMNode);
|
||||
|
@ -14,6 +14,7 @@ const RELATION_LABEL_FOR = nsIAccessibleRelation.RELATION_LABEL_FOR;
|
||||
const RELATION_LABELLED_BY = nsIAccessibleRelation.RELATION_LABELLED_BY;
|
||||
const RELATION_MEMBER_OF = nsIAccessibleRelation.RELATION_MEMBER_OF;
|
||||
const RELATION_NODE_CHILD_OF = nsIAccessibleRelation.RELATION_NODE_CHILD_OF;
|
||||
const RELATION_NODE_PARENT_OF = nsIAccessibleRelation.RELATION_NODE_PARENT_OF;
|
||||
const RELATION_PARENT_WINDOW_OF = nsIAccessibleRelation.RELATION_PARENT_WINDOW_OF;
|
||||
const RELATION_POPUP_FOR = nsIAccessibleRelation.RELATION_POPUP_FOR;
|
||||
const RELATION_SUBWINDOW_OF = nsIAccessibleRelation.RELATION_SUBWINDOW_OF;
|
||||
|
@ -71,7 +71,8 @@
|
||||
testRelation("treeitem3", RELATION_NODE_CHILD_OF, "tree");
|
||||
testRelation("treeitem4", RELATION_NODE_CHILD_OF, "tree");
|
||||
testRelation("treeitem5", RELATION_NODE_CHILD_OF, "treeitem4");
|
||||
testRelation("treeitem6", RELATION_NODE_CHILD_OF, "treeitem5");
|
||||
testRelation("treeitem6", RELATION_NODE_CHILD_OF, "tree");
|
||||
testRelation("treeitem7", RELATION_NODE_CHILD_OF, "treeitem6");
|
||||
|
||||
// 'node child of' relation for row role of treegrid
|
||||
testRelation("treegridrow1", RELATION_NODE_CHILD_OF, "treegrid");
|
||||
@ -86,6 +87,19 @@
|
||||
var iframeDocAcc = getAccessible(iframeDoc);
|
||||
testRelation(iframeDocAcc, RELATION_NODE_CHILD_OF, iframeAcc);
|
||||
|
||||
// 'node parent of' relation on ARIA tree and treegrid.
|
||||
testRelation("tree", RELATION_NODE_PARENT_OF,
|
||||
["treeitem1", "treeitem2", // aria-owns
|
||||
"treeitem3", "treeitem4", "treeitem6"]); // children
|
||||
testRelation("treeitem4", RELATION_NODE_PARENT_OF,
|
||||
"treeitem5"); // aria-level
|
||||
testRelation("treeitem6", RELATION_NODE_PARENT_OF,
|
||||
"treeitem7"); // // group role
|
||||
|
||||
testRelation("treegridrow2", RELATION_NODE_PARENT_OF, "treegridrow3");
|
||||
testRelation("treegrid", RELATION_NODE_PARENT_OF,
|
||||
["treegridrow1", "treegridrow2"]);
|
||||
|
||||
// aria-controls
|
||||
getAccessible("tab");
|
||||
todo(false,
|
||||
@ -141,22 +155,27 @@
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=475298"
|
||||
title="mochitests for accessible relations">
|
||||
Mozilla Bug 475298
|
||||
Bug 475298
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=527461"
|
||||
title="Implement RELATION_NODE_PARENT_OF">
|
||||
Bug 527461
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=558036"
|
||||
title="make HTML <output> accessible">
|
||||
Mozilla Bug 558036
|
||||
Bug 558036
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=682790"
|
||||
title="Ignore implicit label association when it's associated explicitly">
|
||||
Mozilla Bug 682790
|
||||
Bug 682790
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=687393"
|
||||
title="HTML select options gets relation from containing label">
|
||||
Mozilla Bug 687393
|
||||
Bug 687393
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
@ -227,8 +246,9 @@
|
||||
<div role="treeitem" id="treeitem3">Blue</div>
|
||||
<div role="treeitem" id="treeitem4" aria-level="1">Green</div>
|
||||
<div role="treeitem" id="treeitem5" aria-level="2">Light green</div>
|
||||
<div role="treeitem" id="treeitem6" aria-level="1">Green2</div>
|
||||
<div role="group">
|
||||
<div role="treeitem" id="treeitem6">Super light green</div>
|
||||
<div role="treeitem" id="treeitem7">Super light green</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -47,6 +47,11 @@
|
||||
var treeitem6 = treeitem5.nextSibling;
|
||||
testRelation(treeitem6, RELATION_NODE_CHILD_OF, [tree]);
|
||||
|
||||
testRelation(tree, RELATION_NODE_PARENT_OF,
|
||||
[treeitem1, treeitem2, treeitem5, treeitem6]);
|
||||
testRelation(treeitem2, RELATION_NODE_PARENT_OF,
|
||||
[treeitem3, treeitem4]);
|
||||
|
||||
// treeitems and treecells shouldn't pick up relations from tree
|
||||
testRelation(treeitem1, RELATION_LABELLED_BY, null);
|
||||
testRelation(treeitem1.firstChild, RELATION_LABELLED_BY, null);
|
||||
@ -64,12 +69,17 @@
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
|
||||
title="Reorganize implementation of XUL tree accessibility">
|
||||
Mozilla Bug 503727
|
||||
Bug 503727
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=527461"
|
||||
title="Implement RELATION_NODE_PARENT_OF">
|
||||
Bug 527461
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=691248"
|
||||
title="XUL tree items shouldn't pick up relations from XUL tree">
|
||||
Mozilla Bug 691248
|
||||
Bug 691248
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
Loading…
Reference in New Issue
Block a user